def setUp(self): self.user = User(username='******') self.user.save() self.group = Group(name='Group 1', slug='group1') self.group.save() self.accounts = [ Account(name='Account 1', slug='account1', group=self.group), Account(name='Account 2', slug='account2', group=self.group), Account(name='Account 3', slug='account3', group=self.group), ] for account in self.accounts: account.save() self.before = datetime.datetime.now() self.transaction = Transaction(group=self.group) self.transaction.save() self.transaction.entry_set.add( TransactionEntry(account=self.accounts[0], debit=100)) self.transaction.entry_set.add( TransactionEntry(account=self.accounts[1], credit=100)) self.transaction.set_pending(user=self.user) self.after = datetime.datetime.now()
def bill_create_transaction(request, group, bill, is_admin=False): if not bill.is_editable(): messages.info(request, _('This bill is already linked to a transaction.')) return HttpResponseRedirect( reverse('transaction-details', args=[group.slug, bill.transaction.id])) if request.method != 'POST': form = CreateTransactionForm(bill) else: form = CreateTransactionForm(bill, request.POST) if form.is_valid(): pay_to = Account.objects.get( group=group, roleaccount__role=form.cleaned_data['pay_to']) charge_to = form.cleaned_data['charge_to'] settlement = form.cleaned_data.get('settlement', None) sum = 0 for line in bill.billingline_set.all(): sum += line.amount transaction = Transaction(group=group, settlement=settlement) transaction.save() transaction.entry_set.add( TransactionEntry(account=charge_to, credit=sum)) transaction.entry_set.add( TransactionEntry(account=pay_to, debit=sum)) transaction.set_pending( user=request.user, message=_('Bill #%(id)s: %(description)s') % { 'id': bill.pk, 'description': bill.description }) bill.transaction = transaction bill.save() return HttpResponseRedirect( reverse('transaction-details', args=[group.slug, transaction.id])) return render_to_response('billing/bill_create_transaction.html', { 'is_admin': is_admin, 'group': group, 'bill': bill, 'form': form, }, context_instance=RequestContext(request))
def testAccountOnlyOnceInTransaction(self): """Checks that multiple credit accounts are allowed in a transaction""" transaction = Transaction(group=self.group) transaction.save() transaction.entry_set.add( TransactionEntry(account=self.accounts[0], debit=200)) transaction.entry_set.add( TransactionEntry(account=self.accounts[1], credit=100)) transaction.entry_set.add( TransactionEntry(account=self.accounts[2], credit=100)) transaction.delete()
def testEqualDebitAndCreditAmount(self): """Checks that transaction only accept sum(debit)==sum(credit)""" transaction = Transaction(group=self.group) transaction.save() transaction.entry_set.add( TransactionEntry(account=self.accounts[1], debit=200)) transaction.entry_set.add( TransactionEntry(account=self.accounts[0], credit=100)) with self.assertRaises(InvalidTransaction): transaction.set_pending(user=self.user) transaction.delete()
class EntryTestCase(unittest.TestCase): def setUp(self): self.user = User(username='******') self.user.save() self.group = Group(name='group1', slug='group1') self.group.save() self.account = Account(name='account1', slug='account1', group=self.group) self.account.save() self.transaction = Transaction(group=self.group) self.transaction.save() self.entry = TransactionEntry(account=self.account, debit=100, credit=100, transaction=self.transaction) def tearDown(self): self.transaction.delete() self.account.delete() self.group.delete() self.user.delete() def testDebitAndCreditInSameEntry(self): """Checks that setting both debit and credit does not fail""" self.entry.debit = 100 self.entry.credit = 100 self.entry.save() def testNegativeCredit(self): """Checks that inputing av negative credit raises an error""" self.entry.credit = -100 with self.assertRaises(InvalidTransactionEntry): self.entry.save() def testNegativeDebit(self): """Checks that inputing av negative debit raises an error""" self.entry.debit = -100 with self.assertRaises(InvalidTransactionEntry): self.entry.save() def testDebitAndCreditSetToZero(self): """Checks that setting both debit and credit to zero raises error""" self.entry.debit = 0 self.entry.credit = 0 with self.assertRaises(InvalidTransactionEntry): self.entry.save()
def setUp(self): self.user = User(username='******') self.user.save() self.group = Group(name='group1', slug='group1') self.group.save() self.account = Account(name='account1', slug='account1', group=self.group) self.account.save() self.transaction = Transaction(group=self.group) self.transaction.save() self.entry = TransactionEntry(account=self.account, debit=100, credit=100, transaction=self.transaction)
class EntryTestCase(unittest.TestCase): def setUp(self): self.user = User(username="******") self.user.save() self.group = Group(name="group1", slug="group1") self.group.save() self.account = Account(name="account1", slug="account1", group=self.group) self.account.save() self.transaction = Transaction(group=self.group) self.transaction.save() self.entry = TransactionEntry(account=self.account, debit=100, credit=100, transaction=self.transaction) def tearDown(self): self.transaction.delete() self.account.delete() self.group.delete() self.user.delete() def testDebitAndCreditInSameEntry(self): """Checks that setting both debit and credit does not fail""" self.entry.debit = 100 self.entry.credit = 100 self.entry.save() def testNegativeCredit(self): """Checks that inputing av negative credit raises an error""" self.entry.credit = -100 with self.assertRaises(InvalidTransactionEntry): self.entry.save() def testNegativeDebit(self): """Checks that inputing av negative debit raises an error""" self.entry.debit = -100 with self.assertRaises(InvalidTransactionEntry): self.entry.save() def testDebitAndCreditSetToZero(self): """Checks that setting both debit and credit to zero raises error""" self.entry.debit = 0 self.entry.credit = 0 with self.assertRaises(InvalidTransactionEntry): self.entry.save()
def setUp(self): self.user = User(username="******") self.user.save() self.group = Group(name="group1", slug="group1") self.group.save() self.account = Account(name="account1", slug="account1", group=self.group) self.account.save() self.transaction = Transaction(group=self.group) self.transaction.save() self.entry = TransactionEntry(account=self.account, debit=100, credit=100, transaction=self.transaction)
def transaction_entries(self): if not self.is_valid(): return None credit_account = self.cleaned_data['credit_account'] entries = [] total = 0 for account, fields in self.account_fields: amount = 0 for name, field in fields: count = self.cleaned_data.get(name, 0) or 0 price = self.cleaned_data['-'.join(name.split('-')[:-1])] amount += count * price if amount > 0: total += amount entries.append(TransactionEntry(account=account, debit=amount)) if total > 0: entries.append( TransactionEntry(account=credit_account, credit=total)) return entries
def setUp(self): self.users = [ User(username='******'), User(username='******'), User(username='******'), ] for user in self.users: user.save() self.group = Group(name='Group 1', slug='group1') self.group.save() self.accounts = [ # Normal user account Account(name='Account 1', slug='account1', group=self.group, owner=self.users[0]), # Normal user account Account(name='Account 2', slug='account2', group=self.group, owner=self.users[1]), # Inactive user account Account(name='Account 3', slug='account3', group=self.group, owner=self.users[2], active=False), # Group account Account(name='Account 4', slug='account4', group=self.group, type=Account.ASSET_ACCOUNT), # Inactive group account Account(name='Account 5', slug='account5', group=self.group, type=Account.ASSET_ACCOUNT, active=False), # Bank account self.group.roleaccount_set.get(role=RoleAccount.BANK_ACCOUNT ).account, # Cash account self.group.roleaccount_set.get(role=RoleAccount.CASH_ACCOUNT ).account, ] for account in self.accounts: account.save() self.account = self.accounts[0] self.transactions = { 'Pen': Transaction(group=self.group), 'Com': Transaction(group=self.group), 'Rej': Transaction(group=self.group), } values = { 'Pen': 150, 'Com': 200, 'Rej': 100, } for state, transaction in self.transactions.items(): transaction.save() transaction.entry_set.add( TransactionEntry(account=self.accounts[0], credit=values[state])) transaction.entry_set.add( TransactionEntry(account=self.accounts[1], debit=values[state])) transaction.set_pending(user=self.users[0]) self.transactions['Undef'] = Transaction(group=self.group) self.transactions['Undef'].save() self.transactions['Com'].set_committed(user=self.users[2]) self.transactions['Rej'].set_rejected(user=self.users[2])
def transfer( request, group, account=None, transfer_type=None, is_admin=False, is_owner=False): """Deposit, withdraw or transfer money""" if request.method == 'POST': data = request.POST else: data = None if transfer_type == 'transfer': title = _('Transfer from account') form = TransferForm(data, account=account) elif transfer_type == 'deposit': title = _('Deposit to account') form = DepositWithdrawForm(data) elif transfer_type == 'withdraw': title = _('Withdrawal from account') form = DepositWithdrawForm(data) else: return HttpResponseForbidden(_('Forbidden if not group admin.')) if request.method == 'POST' and form.is_valid(): amount = form.cleaned_data['amount'] details = form.cleaned_data['details'].strip() if details == '': details = None bank_account = group.roleaccount_set.get( role=RoleAccount.BANK_ACCOUNT).account transaction = Transaction(group=group) # FIXME: save() shouldn't be need if we figure out a reasonable hack transaction.save() if transfer_type == 'deposit': # Deposit to user account transaction.entry_set.add( TransactionEntry(account=account, credit=amount)) transaction.entry_set.add( TransactionEntry(account=bank_account, debit=amount)) transaction.set_pending(user=request.user, message=details) elif transfer_type == 'withdraw': # Withdraw from user account transaction.entry_set.add( TransactionEntry(account=account, debit=amount)) transaction.entry_set.add( TransactionEntry(account=bank_account, credit=amount)) transaction.set_pending(user=request.user, message=details) elif transfer_type == 'transfer': # Transfer from user account to other user account credit_account = Account.objects.get( id=form.cleaned_data['credit_account']) transaction.entry_set.add( TransactionEntry(account=account, debit=amount)) transaction.entry_set.add( TransactionEntry(account=credit_account, credit=amount)) transaction.set_pending(user=request.user, message=details) if amount <= account.normal_balance() - (group.block_limit or 0): transaction.set_committed(user=request.user) else: messages.info(request, _( 'Your transaction has been added, ' 'but your group admin has to commit it.')) else: return HttpResponseForbidden(_('Forbidden if not group admin.')) messages.success(request, _('Added transaction: %s') % transaction) return HttpResponseRedirect(reverse( 'account-summary', args=[account.group.slug, account.slug])) return render_to_response('accounting/transfer.html', { 'is_admin': is_admin, 'is_owner': is_owner, 'account': account, 'type': transfer_type, 'title': title, 'form': form, 'group': group, }, context_instance=RequestContext(request))
def new_edit_transaction(request, group, transaction=None, is_admin=False): """Admin view for creating transactions""" if transaction is None: transaction = Transaction(group=group) elif not transaction.is_editable(): messages.error( request, _('Transaction %d can\'t be changed.' % transaction.id)) db_transaction.commit() url = reverse('group-summary', args=(group.slug,)) return HttpResponseRedirect(url) if request.method == 'POST': data = request.POST elif transaction.id: data = {} # Load "fake" post data if we are editing a transaction for e in transaction.entry_set.all(): if e.debit > 0: data['%d-debit' % e.account.id] = e.debit if e.credit > 0: data['%d-credit' % e.account.id] = e.credit data['settlement-settlement'] = transaction.settlement_id else: data = None # Init forms settlement_form = TransactionSettlementForm( data, prefix='settlement', instance=transaction) user_forms = [] group_forms = [] for account in ufs_sorted(group.user_account_set.filter(active=True)): user_forms.append((account, EntryForm(data, prefix=account.id))) for account in ufs_sorted(group.group_account_set.filter(active=True)): group_forms.append((account, EntryForm(data, prefix=account.id))) errors = [] if request.method == 'POST' and settlement_form.is_valid(): entries = {} if transaction.id is None: transaction.save() else: for e in transaction.entry_set.all(): entries[e.account.id] = e transaction.settlement = settlement_form.cleaned_data['settlement'] try: for forms in [group_forms, user_forms]: for account, form in forms: if not form.is_valid(): raise InvalidTransaction( 'Form was not valid, id: %d' % account.id) else: credit = form.cleaned_data['credit'] debit = form.cleaned_data['debit'] if account.id in entries: entry = entries[account.id] else: entry = TransactionEntry( account=account, transaction=transaction) if credit > 0 or debit > 0: entry.credit = credit or 0 entry.debit = debit or 0 entry.save() elif entry.id: entry.delete() details = settlement_form.cleaned_data['details'] transaction.save() transaction.set_pending(user=request.user, message=details) messages.success(request, _('Your transaction has been added.')) except InvalidTransaction, e: errors.append(e) db_transaction.rollback() else: db_transaction.commit() url = reverse('group-summary', args=(group.slug,)) return HttpResponseRedirect(url)
def new_edit_transaction(request, group, transaction=None, is_admin=False): """Admin view for creating transactions""" savepoint_id = db_transaction.savepoint() if transaction is None: transaction = Transaction(group=group) elif not transaction.is_editable(): messages.error(request, _("Transaction %d can't be changed." % transaction.id)) db_transaction.savepoint_rollback(savepoint_id) url = reverse("group-summary", args=(group.slug, )) return HttpResponseRedirect(url) if request.method == "POST": data = request.POST elif transaction.id: data = {} # Load "fake" post data if we are editing a transaction for e in transaction.entry_set.all(): if e.debit > 0: data["%d-debit" % e.account.id] = e.debit if e.credit > 0: data["%d-credit" % e.account.id] = e.credit data["settlement-settlement"] = transaction.settlement_id else: data = None # Init forms settlement_form = TransactionSettlementForm(data, prefix="settlement", instance=transaction) user_forms = [] group_forms = [] for account in ufs_sorted(group.user_account_set.filter(active=True)): user_forms.append((account, EntryForm(data, prefix=account.id))) for account in ufs_sorted(group.group_account_set.filter(active=True)): group_forms.append((account, EntryForm(data, prefix=account.id))) errors = [] if request.method == "POST" and settlement_form.is_valid(): entries = {} if transaction.id is None: transaction.save() else: for e in transaction.entry_set.all(): entries[e.account.id] = e transaction.settlement = settlement_form.cleaned_data["settlement"] try: for forms in [group_forms, user_forms]: for account, form in forms: if not form.is_valid(): raise InvalidTransaction("Form was not valid, id: %d" % account.id) else: credit = form.cleaned_data["credit"] or 0 debit = form.cleaned_data["debit"] or 0 if account.id in entries: entry = entries[account.id] else: entry = TransactionEntry(account=account, transaction=transaction) if credit > 0 or debit > 0: entry.credit = credit or 0 entry.debit = debit or 0 entry.save() elif entry.id: entry.delete() details = settlement_form.cleaned_data["details"] transaction.save() transaction.set_pending(user=request.user, message=details) messages.success(request, _("Your transaction has been added.")) except InvalidTransaction as e: errors.append(e) db_transaction.savepoint_rollback(savepoint_id) else: db_transaction.savepoint_commit(savepoint_id) url = reverse("group-summary", args=(group.slug, )) return HttpResponseRedirect(url) db_transaction.savepoint_rollback(savepoint_id) return render( request, "accounting/transaction_form.html", { "is_admin": is_admin, "group": group, "settlement_form": settlement_form, "group_forms": group_forms, "user_forms": user_forms, "errors": errors, "transaction": transaction, }, )