Display protocoin amounts, improve transaction validation
This commit is contained in:
		| @@ -3,6 +3,7 @@ logger = logging.getLogger(__name__) | ||||
|  | ||||
| from django.contrib.auth.models import User, Group | ||||
| 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 rest_framework import serializers | ||||
| from rest_framework.exceptions import ValidationError | ||||
| @@ -77,13 +78,21 @@ class TransactionSerializer(serializers.ModelSerializer): | ||||
|             'paypal_payer_id', | ||||
|         ] | ||||
|  | ||||
|     def create(self, validated_data): | ||||
|     def validate_transaction(self, validated_data): | ||||
|         if not self.initial_data.get('member_id', None): | ||||
|             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 | ||||
|  | ||||
|         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': | ||||
|             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.')) | ||||
|             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['amount'] == 0: | ||||
|                 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': | ||||
|             msg = 'Manual PayPal transaction added:\n' + str(validated_data) | ||||
|             utils.alert_tanner(msg) | ||||
| @@ -104,18 +132,10 @@ class TransactionSerializer(serializers.ModelSerializer): | ||||
|             msg = 'Manual Protocoin transaction added:\n' + str(validated_data) | ||||
|             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) | ||||
|  | ||||
|     def update(self, instance, validated_data): | ||||
|         if not self.initial_data.get('member_id', None): | ||||
|             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 | ||||
|         validated_data = self.validate_transaction(validated_data) | ||||
|         return super().update(instance, validated_data) | ||||
|  | ||||
|     def get_member_id(self, obj): | ||||
| @@ -183,6 +203,7 @@ class MemberSerializer(serializers.ModelSerializer): | ||||
|     crop = serializers.CharField(write_only=True, required=False) | ||||
|     email = fields.UserEmailField(serializers.EmailField) | ||||
|     phone = serializers.CharField() | ||||
|     protocoin = serializers.SerializerMethodField() | ||||
|  | ||||
|     class Meta: | ||||
|         model = models.Member | ||||
| @@ -221,6 +242,11 @@ class MemberSerializer(serializers.ModelSerializer): | ||||
|             '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): | ||||
|         instance.user.email = validated_data.get('email', instance.user.email) | ||||
|         instance.user.save() | ||||
|   | ||||
| @@ -539,6 +539,11 @@ export function AdminMemberInfo(props) { | ||||
| 						</Table.Cell> | ||||
| 					</Table.Row> | ||||
|  | ||||
| 					<Table.Row> | ||||
| 						<Table.Cell>Protocoin:</Table.Cell> | ||||
| 						<Table.Cell>₱ {member.protocoin.toFixed(2)}</Table.Cell> | ||||
| 					</Table.Row> | ||||
|  | ||||
| 					<Table.Row> | ||||
| 						<Table.Cell>Application Date:</Table.Cell> | ||||
| 						<Table.Cell>{member.application_date}</Table.Cell> | ||||
|   | ||||
| @@ -48,6 +48,10 @@ function MemberInfo(props) { | ||||
| 									{member.status || 'Unknown'} | ||||
| 								</Table.Cell> | ||||
| 							</Table.Row> | ||||
| 							<Table.Row> | ||||
| 								<Table.Cell>Protocoin:</Table.Cell> | ||||
| 								<Table.Cell>₱ {member.protocoin.toFixed(2)}</Table.Cell> | ||||
| 							</Table.Row> | ||||
| 							<Table.Row> | ||||
| 								<Table.Cell>Expiry:</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> | ||||
| 								</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> | ||||
| 						) | ||||
| 					: | ||||
|   | ||||
| @@ -159,7 +159,6 @@ export function TransactionEditor(props) { | ||||
| 					{...makeProps('memo')} | ||||
| 				/> | ||||
| 			</Form.Group> | ||||
|  | ||||
| 		</div> | ||||
| 	); | ||||
| }; | ||||
| @@ -304,7 +303,7 @@ export function TransactionList(props) { | ||||
| 									x.member_name | ||||
| 								} | ||||
| 							</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> | ||||
| 							{!noCategory && <Table.Cell>{x.category}</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.Cell>Amount:</Table.Cell> | ||||
| 						<Table.Cell>${transaction.amount}</Table.Cell> | ||||
| 						<Table.Cell>$ {transaction.amount}</Table.Cell> | ||||
| 					</Table.Row> | ||||
| 					{transaction.protocoin !== '0.00' && <Table.Row> | ||||
| 						<Table.Cell>Protocoin:</Table.Cell> | ||||
| 						<Table.Cell>₱ {transaction.protocoin}</Table.Cell> | ||||
| 					</Table.Row>} | ||||
| 					<Table.Row> | ||||
| 						<Table.Cell>Category:</Table.Cell> | ||||
| 						<Table.Cell>{transaction.category}</Table.Cell> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user