Esempio n. 1
0
    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()
Esempio n. 2
0
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))
Esempio n. 3
0
    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()
Esempio n. 4
0
    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()
Esempio n. 5
0
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()
Esempio n. 6
0
    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)
Esempio n. 7
0
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()
Esempio n. 8
0
    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)
Esempio n. 9
0
    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
Esempio n. 10
0
    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])
Esempio n. 11
0
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))
Esempio n. 12
0
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)
Esempio n. 13
0
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,
        },
    )