def remove_participants(event, leavers): # check, that leaver is participated leavers = is_participated(event, leavers) if not leavers: return participants = Participation.objects.filter(event=event, active=True) exist_parts = participants.aggregate(s=Sum('parts'))['s'] exist_parts = 0.0 if exist_parts is None else exist_parts # fix None party_pay = event.price / exist_parts rest_participations = participants.filter(~Q(account__in=leavers)) leaver_participations = participants.filter(account__in=list(leavers)) # return money for participation in leaver_participations: leaver_transaction = Transaction(participation=participation, type=Transaction.OUT) debit = party_pay * participation.parts leaver_transaction.debit = debit leaver_transaction.save() # create diffs # yep folks, you should pay for this leavers rest_parts = rest_participations.aggregate(s=Sum('parts'))['s'] for victum in rest_participations: credit = ((leaver_transaction.debit / rest_parts) * victum.parts) delegate_debt(victum, credit, leaver_transaction) leaver_participations.update(active=False)
def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) try: Transaction.make_transaction(**serializer.validated_data) except InvalidAmount as err: content = {err.default_code: err.detail} status_code = err.status_code return Response(content, status=status_code) return Response(serializer.data, status=status.HTTP_201_CREATED)
def deposit_api_account(): id = int(request.get_json()['id']) amt = int(request.get_json()['amt']) account = Account.query.filter_by(accountid=id).first() if account and account.status == "active": pb = account.amount cust = Customer.query.filter_by(customerid=account.customerid).first() cust.message = "Withdrwan money from the linked account" account.message = "Money withdrawn from the account" account.last_update = datetime.now().strftime("%d-%m-%Y, %H:%M:%S %p") cust.last_update = datetime.now().strftime("%d-%m-%Y, %H:%M:%S %p") account.amount = pb + amt transac = Transaction(customerid=account.customerid, accountid=account.accountid, sourceAccType=account.accType, targetAccType=account.accType, destAccNum=str(id), amount=amt) db.session.add(transac) db.session.commit() return jsonify({ 'aid': id, 'cid': account.customerid, 'pb': pb, 'cb': account.amount }) else: return jsonify({ 'error': "Account might not be created or it is pending to be activated" })
def test_transaction_fail_amount(self): initial_balance = 0 trans_amount = 100 account = Account.objects.create( holder=self.user, balance=initial_balance, status=Account.ACTIVE ) with self.assertRaises(InvalidAmount): Transaction.make_transaction( account=account, merchant='GH', amount=trans_amount, comment='For you' )
def add_participants(event, newbies): """Add participants in event. Takes dict, where keys - is account models and values is participation part(int).""" if len(newbies) == 0: return # calc party-pay, participants = Participation.objects.filter(event=event, active=True) exist_parts = participants.aggregate(s=Sum('parts'))['s'] exist_parts = 0.0 if exist_parts is None else exist_parts # fix None all_parts = exist_parts + sum(newbies.values()) party_pay = event.price / all_parts recalcers = participants.filter(~Q(account__in=newbies.keys())) parent_transactions = [] # participate incomers for (acc, parts) in newbies.items(): # if not already participated participation = Participation.objects.filter(account=acc, event=event, active=False) if len(participation) == 0: participation = Participation(account=acc, parts=parts, event=event) else: participation = participation[0] participation.active = True participation.save() tr = Transaction(participation=participation, type=Transaction.PARTICIPATE) tr.credit = party_pay * parts parent_transactions.append(tr) tr.save() # create diffs for old participants # if no recalcers(incomers if first participants) we have exist_parts = 0 for newbie_transaction in parent_transactions: for participation in recalcers: assert (exist_parts != 0),\ "On add participants when we need recalc exist participants\ exist_parts should be positive(not zero)" debit = ((newbie_transaction.credit / exist_parts) * participation.parts) return_money(participation, debit, newbie_transaction)
def add_participants(event, newbies): """Add participants in event. Takes dict, where keys - is account models and values is participation part(int).""" # calc party-pay, participants = Participation.objects.filter(event=event, active=True) exist_parts = participants.aggregate(s=Sum('parts'))['s'] exist_parts = 0.0 if exist_parts is None else exist_parts # fix None all_parts = exist_parts + sum(newbies.values()) party_pay = event.price / all_parts recalcers = participants.filter(~Q(account__in=newbies.keys())) parent_transactions = [] # participate incomers for (acc, parts) in newbies.items(): # if not already participated participation = Participation.objects.filter(account=acc, active=False) if len(participation) == 0: participation = Participation(account=acc, parts=parts, event=event) else: participation = participation[0] participation.active = True participation.save() tr = Transaction(participation=participation, type=Transaction.PARTICIPATE) tr.credit = party_pay * parts parent_transactions.append(tr) tr.save() # create diffs for old participants # if no recalcers(incomers if first participants) we have exist_parts = 0 for newbie_transaction in parent_transactions: for participation in recalcers: assert (exist_parts != 0),\ "On add participants when we need recalc exist participants\ exist_parts should be positive(not zero)" debit = ((newbie_transaction.credit / exist_parts) * participation.parts) return_money(participation, debit, newbie_transaction)
def delegate_debt(participation, credit, parent): """Make diff transactions for given participation(event,user) with given credit. This means, that we get money from user and spend it to event. @param participation: Event-User link that for create transaction @type participation: Participation @param debit: Money count that was returned @type debit: float @param parent: Parent transaction, that initiate return(incomer for example) @type parent: Transaction """ t = Transaction(participation=participation, type=Transaction.DIFF, parent=parent) t.credit = credit t.save()
def test_transfer(self): initial_balance = 300 trans_amount = 100 account = Account.objects.create( holder=self.user, balance=initial_balance, status=Account.ACTIVE ) Transaction.make_transaction( account=account, merchant='GH', amount=trans_amount, comment='For you' ) transaction = Transaction.objects.all().first() self.assertIsInstance(transaction, Transaction) self.assertEqual(transaction.__str__(), f'Account {transaction.account.uid} sent {transaction.amount} to {transaction.merchant}')
def test_transaction(self): initial_balance = 300 trans_amount = 100 account = Account.objects.create( holder=self.user, balance=initial_balance, status=Account.ACTIVE ) Transaction.make_transaction( account=account, merchant='GH', amount=trans_amount, comment='For you' ) expected_balance = initial_balance - trans_amount transaction = Transaction.objects.all() self.assertEqual(account.balance, expected_balance) self.assertEqual(len(transaction), 1)
def transfer_api_account(): data = request.get_json() acc1 = Account.query.filter_by(accountid=int(data["baid"])).first() acc2 = Account.query.filter_by(accountid=int(data["daid"])).first() if acc2 and acc1.amount >= int(data["amount"]): pb1 = acc1.amount pb2 = acc2.amount acc1.amount -= int(data['amount']) acc2.amount += int(data['amount']) acc1.message = "Money debited and transferred from the account" acc1.last_update = datetime.now().strftime("%d-%m-%Y, %H:%M:%S %p") acc2.message = "Money credited to the account by transfer" acc2.last_update = datetime.now().strftime("%d-%m-%Y, %H:%M:%S %p") transac = Transaction(customerid=acc1.customerid, accountid=acc1.accountid, message=f"Transfer to account {acc2.accountid}", sourceAccType=acc1.accType, targetAccType=acc2.accType, destAccNum=acc2.accountid, amount=int(data['amount'])) cust1 = Customer.query.filter_by(customerid=acc1.customerid).first() cust2 = Customer.query.filter_by(customerid=acc2.customerid).first() cust1.message = "Money debited from the account " + str(acc1.accountid) cust2.message = "Money credited to the account " + str(acc2.accountid) cust1.last_update = datetime.now().strftime("%d-%m-%Y, %H:%M:%S %p") cust2.last_update = datetime.now().strftime("%d-%m-%Y, %H:%M:%S %p") db.session.add(transac) db.session.commit() return jsonify({ 'pb1': pb1, 'pb2': pb2, 'cb1': acc1.amount, 'cb2': acc2.amount }) elif acc1.amount < int(data["amount"]): return jsonify({ 'error': "Your Account doesnt have required funds to be transferred" }) else: return jsonify({ 'error': "The recievers account has not either created or accepted yet" })
def api_withdraw_account(): data = request.get_json() acc = Account.query.filter_by(accountid=data['id']).first() if data['id'] and not data['withdraw'] and acc and acc.status == 'active': return jsonify({'balance': acc.amount}) elif (data['id'] and not data['withdraw'] and (acc is None or acc.status != 'active')) or (data['id'] and data['withdraw'] and not acc): return jsonify({ 'error': "The account cannot be recognized in our database or still the account must be accepted" }) elif data['id'] and data['withdraw'] and acc and acc.status == 'active': json = dict() json['pb'] = acc.amount transac = Transaction(customerid=acc.customerid, accountid=acc.accountid, message="Money withdrawn", sourceAccType=acc.accType, targetAccType=acc.accType, destAccNum=acc.accountid, amount=acc.amount - int(data['amount'])) print(acc.customerid) cust = Customer.query.filter_by(customerid=acc.customerid).first() cust.message = "Withdrwan money from the linked account" acc.message = "Money withdrawn from the account" acc.last_update = datetime.now().strftime("%d-%m-%Y, %H:%M:%S %p") cust.last_update = datetime.now().strftime("%d-%m-%Y, %H:%M:%S %p") acc.amount = acc.amount - int(data['amount']) db.session.add(transac) db.session.commit() json['aid'] = acc.accountid json['cbal'] = acc.amount return jsonify(json)