Пример #1
0
 def update(self, accountid):
     account = self.__own_account(accountid)
     if not account:
         self.notfound(
            'Nonexistent account cannot be modified (or you do not own it)')
     if 'name' in self.args:
         account.name = self.args['name']
     if 'currency' in self.args:
         # Do not update currency if account has transactions
         if not models.TransactionAccount.query.filter(
                     models.TransactionAccount.account == account
                ).count():
             currency = core.Currency.query.filter(
                 db.and_(
                     core.Currency.isocode == self.args['currency'],
                     db.or_(
                         core.Currency.owner_username == self.username,
                         core.Currency.owner_username == None
                     )
                 )
             ).first()
             if currency:
                 account.currency = currency
     if 'start_balance' in self.args:
         account.start_balance = Decimal(self.args['start_balance'])
         self.add_to_response('totalbalance')
     db.session.commit()
     return account.as_dict(self.username)
Пример #2
0
def delete_everything(username):
    """Delete all data except user preferences"""
    # Transaction
    #  -> TransactionAccount and TransactionCategory deleted by cascade
    transaction.Transaction.query.filter(
        transaction.Transaction.owner_username == username).delete()
    # Category
    transaction.Category.query.filter(
        transaction.Category.owner_username == username).delete()
    # Account
    # ... first get all accounts for the user...
    accountowners = transaction.AccountOwner.query.filter(
        transaction.AccountOwner.owner_username == username).all()
    # ... then delete all "AccountOwner" links for the user...
    transaction.AccountOwner.query.filter(
        transaction.AccountOwner.owner_username == username).delete()
    # ... and delete only accounts which do not have user associated...
    deleteaccounts = []
    for accountowner in accountowners:
        if not transaction.AccountOwner.query.filter(
                transaction.AccountOwner.account_id ==
                accountowner.account_id).first():
            deleteaccounts.append(
                transaction.Account.id == accountowner.account_id)
    if deleteaccounts:
        transaction.Account.query.filter(db.or_(*deleteaccounts)).delete()
    # Currency
    core.Currency.query.filter(
        core.Currency.owner_username == username).delete()
    # XXX TransactionAccounts are not deleted : problem with SQLite
    # Commit deletes
    db.session.commit()
Пример #3
0
    def __search(self, substring):
        """Search on parts of the users name or on exact email address"""
        if len(substring) < 3:
            self.badrequest('Please give at least 3 characters')
        if '@' in substring:
            corresponding_rows = models.User.query.join(
                                    models.UserEmail
            ).filter(
                models.UserEmail.email_address == substring,
                models.UserEmail.confirmation == 'OK'
            )
        else:
            substring=u'%{0}%'.format(substring)
            corresponding_rows = models.User.query.filter(
                db.and_(
                    models.User.username != self.username,
                    db.or_(
                        models.User.username.like(substring),
                        models.User.first_name.like(substring),
                        models.User.last_name.like(substring),
                    )
                )
            )

        return [u.as_dict() for u in corresponding_rows.all()]
Пример #4
0
 def create(self):
     if not ('currency' in self.args and 'name' in self.args):
         self.badrequest("Please provide category name and currency")
     if 'parent' in self.args:
         parent = self.__own_category(self.args['parent'])
         if not parent:
             self.badrequest("This parent category does not exist")
     else:
         parent = None
     currency = core.Currency.query.filter(
         db.and_(
             core.Currency.isocode == self.args['currency'],
             db.or_(
                 core.Currency.owner_username == self.username,
                 core.Currency.owner_username == None
             )
         )
     ).first()
     if not currency:
         self.badrequest("This currency does not exist")
     category = models.Category(
                     owner_username=self.username,
                     parent=parent,
                     currency=currency,
                     name=self.args['name']
                )
     db.session.add(category)
     db.session.commit()
     return category.as_dict(self.username)
Пример #5
0
 def list(self):
     currencies = models.Currency.query.filter(
         db.or_(
             models.Currency.owner_username == self.username,
             models.Currency.owner_username == None,
         ))
     return [c.as_dict() for c in currencies]
Пример #6
0
    def create(self):
        if not (
            'currency' in self.args and
            'name' in self.args and
            'start_balance' in self.args
        ):
            self.badrequest(
                 "Please provide the account name, currency and start balance")
        currency = core.Currency.query.filter(
            db.and_(
                core.Currency.isocode == self.args['currency'],
                db.or_(
                    core.Currency.owner_username == self.username,
                    core.Currency.owner_username == None
                )
            )
        ).first()
        if not currency:
            self.badrequest("This currency does not exist")

        name = self.args['name']
        start_balance = self.args['start_balance']

        a = models.Account(
                name=name,
                currency=currency,
                start_balance=start_balance
        )
        ao = models.AccountOwner(account=a, owner_username=self.username)
        db.session.add_all((a, ao))
        db.session.commit()
        self.add_to_response('totalbalance')
        return a.as_dict(self.username)
Пример #7
0
 def list(self):
     currencies = models.Currency.query.filter(
         db.or_(
             models.Currency.owner_username == self.username,
             models.Currency.owner_username == None,
         )
     )
     return [c.as_dict() for c in currencies]
Пример #8
0
 def __own_currency(self, isocode):
     return models.Currency.query.filter(
         db.and_(
             models.Currency.isocode == isocode,
             db.or_(
                 models.Currency.owner_username == self.username,
                 models.Currency.owner_username == None,
             )))
Пример #9
0
 def __own_currency(self, isocode):
     return models.Currency.query.filter(
         db.and_(
             models.Currency.isocode == isocode,
             db.or_(
                 models.Currency.owner_username == self.username,
                 models.Currency.owner_username == None,
             )
         )
     )
Пример #10
0
def rate(username, fromisocode, toisocode):
    if fromisocode == toisocode:
        return 1
    # Request the currencies
    fromcurrency = core.Currency.query.filter(
        db.and_(
            core.Currency.isocode == fromisocode,
            db.or_(core.Currency.owner_username == username, core.Currency.owner_username == None),
        )
    ).first()
    tocurrency = core.Currency.query.filter(
        db.and_(
            core.Currency.isocode == toisocode,
            db.or_(core.Currency.owner_username == username, core.Currency.owner_username == None),
        )
    ).first()
    if not fromcurrency or not tocurrency:
        return None
    # Both currencies are globally defined
    if (fromcurrency.rate is None) and (tocurrency.rate is None):
        return exchangerate.getrate(fromcurrency.isocode, tocurrency.isocode)
    # Both currencies are user-defined
    elif (fromcurrency.rate is not None) and (tocurrency.rate is not None):
        return tocurrency.rate / fromcurrency.rate
    # Mixed user-defined / globally defined rates
    else:
        preferred_isocode = core.User.query.filter(core.User.username == username).one().preferred_currency.isocode
        # From a user-defined currency to a globally defined currency
        if (fromcurrency.rate is not None) and (tocurrency.rate is None):
            target_rate = exchangerate.getrate(preferred_isocode, tocurrency.isocode)
            if fromcurrency.rate == 0:
                return 0
            return target_rate / fromcurrency.rate
        if (fromcurrency.rate is None) and (tocurrency.rate is not None):
            source_rate = exchangerate.getrate(preferred_isocode, fromcurrency.isocode)
            if tocurrency.rate == 0:
                return 0
            return tocurrency.rate / source_rate
Пример #11
0
 def update(self, categoryid):
     category = self.__own_category(categoryid)
     if not category:
         self.notfound(
           'Nonexistent category cannot be modified (or you do not own it)')
     if 'name' in self.args:
         category.name = self.args['name']
     if 'currency' in self.args:
         currency = core.Currency.query.filter(
             db.and_(
                 core.Currency.isocode == self.args['currency'],
                 db.or_(
                     core.Currency.owner_username == self.username,
                     core.Currency.owner_username == None
                 )
             )
         ).first()
         if currency:
             rate = helpers.rate(
                         self.username,
                         category.currency.isocode,
                         currency.isocode
                    )
             category.currency = currency
             for tc in models.TransactionCategory.query.filter(
                         models.TransactionCategory.category == category
                       ).all():
                 tc.category_amount = tc.category_amount * rate
     if 'parent' in self.args:
         if self.args['parent'] == 'NONE':
             category.parent_id = None
         else:
             parent = self.__own_category(self.args['parent'])
             if not parent:
                 self.badrequest("This parent category does not exist")
             if category.contains_category(parent.id):
                 self.badrequest(
                           "The parent is already a child of this category")
             if parent.id != category.parent_id:
                 allparents = set([parent.id, category.parent_id] + \
                                  parent.all_parents_ids())
                 if category.parent_id:
                     allparents.update(category.parent.all_parents_ids())
                 for parentid in allparents:
                     if parentid:
                         self.add_to_response('categoriesbalance', parentid)
                 category.parent = parent
     db.session.commit()
     return category.as_dict(self.username)
Пример #12
0
def category_filter(value):
    def subcategories(categoryid, categorylist):
        for cat in models.Category.query.filter(
                        models.Category.parent_id == categoryid
                    ):
            categorylist.append(cat.id)
            categorylist = subcategories(cat.id, categorylist)
        return categorylist

    categorylist = subcategories(value, [ int(value) ])
    return [
        models.Transaction.id == models.TransactionCategory.transaction_id,
        db.or_(*[ models.TransactionCategory.category_id == value \
               for value in categorylist ])
    ]
Пример #13
0
 def update(self, categoryid):
     category = self.__own_category(categoryid)
     if not category:
         self.notfound(
             'Nonexistent category cannot be modified (or you do not own it)'
         )
     if 'name' in self.args:
         category.name = self.args['name']
     if 'currency' in self.args:
         currency = core.Currency.query.filter(
             db.and_(
                 core.Currency.isocode == self.args['currency'],
                 db.or_(core.Currency.owner_username == self.username,
                        core.Currency.owner_username == None))).first()
         if currency:
             rate = helpers.rate(self.username, category.currency.isocode,
                                 currency.isocode)
             category.currency = currency
             for tc in models.TransactionCategory.query.filter(
                     models.TransactionCategory.category == category).all():
                 tc.category_amount = tc.category_amount * rate
     if 'parent' in self.args:
         if self.args['parent'] == 'NONE':
             category.parent_id = None
         else:
             parent = self.__own_category(self.args['parent'])
             if not parent:
                 self.badrequest("This parent category does not exist")
             if category.contains_category(parent.id):
                 self.badrequest(
                     "The parent is already a child of this category")
             if parent.id != category.parent_id:
                 allparents = set([parent.id, category.parent_id] + \
                                  parent.all_parents_ids())
                 if category.parent_id:
                     allparents.update(category.parent.all_parents_ids())
                 for parentid in allparents:
                     if parentid:
                         self.add_to_response('categoriesbalance', parentid)
                 category.parent = parent
     db.session.commit()
     return category.as_dict(self.username)
Пример #14
0
def delete_everything(username):
    """Delete all data except user preferences"""
    # Transaction
    #  -> TransactionAccount and TransactionCategory deleted by cascade
    transaction.Transaction.query.filter(
        transaction.Transaction.owner_username == username
    ).delete()
    # Category
    transaction.Category.query.filter(
        transaction.Category.owner_username == username
    ).delete()
    # Account
    # ... first get all accounts for the user...
    accountowners = transaction.AccountOwner.query.filter(
                        transaction.AccountOwner.owner_username == username
                    ).all()
    # ... then delete all "AccountOwner" links for the user...
    transaction.AccountOwner.query.filter(
        transaction.AccountOwner.owner_username == username
    ).delete()
    # ... and delete only accounts which do not have user associated...
    deleteaccounts = []
    for accountowner in accountowners:
        if not transaction.AccountOwner.query.filter(
                transaction.AccountOwner.account_id == accountowner.account_id
        ).first():
            deleteaccounts.append(
                transaction.Account.id == accountowner.account_id
            )
    if deleteaccounts:
        transaction.Account.query.filter(
            db.or_(*deleteaccounts)
        ).delete()
    # Currency
    core.Currency.query.filter(
        core.Currency.owner_username == username
    ).delete()
    # XXX TransactionAccounts are not deleted : problem with SQLite
    # Commit deletes
    db.session.commit()
Пример #15
0
 def create(self):
     if not ('currency' in self.args and 'name' in self.args):
         self.badrequest("Please provide category name and currency")
     if 'parent' in self.args:
         parent = self.__own_category(self.args['parent'])
         if not parent:
             self.badrequest("This parent category does not exist")
     else:
         parent = None
     currency = core.Currency.query.filter(
         db.and_(
             core.Currency.isocode == self.args['currency'],
             db.or_(core.Currency.owner_username == self.username,
                    core.Currency.owner_username == None))).first()
     if not currency:
         self.badrequest("This currency does not exist")
     category = models.Category(owner_username=self.username,
                                parent=parent,
                                currency=currency,
                                name=self.args['name'])
     db.session.add(category)
     db.session.commit()
     return category.as_dict(self.username)
Пример #16
0
    def create(self):
        if not (
            'currency' in self.args and \
            'date' in self.args and \
            'description' in self.args and \
            'amount' in self.args
        ):
            self.badrequest(
           "Please provide transaction description, currency, amount and date")
        # First, create the transaction object
        currency = core.Currency.query.filter(
            db.and_(
                core.Currency.isocode == self.args['currency'],
                db.or_(
                    core.Currency.owner_username == self.username,
                    core.Currency.owner_username == None
                )
            )
        ).first()
        if not currency:
            self.badrequest("This currency does not exist")
        date = helpers.date_from_string(self.args['date'])
        if not date:
            self.badrequest("This date cannot be understood")
        description = self.args['description']
        if 'original_description' in self.args:
            original_description = self.args['original_description']
        else:
            original_description = description
        transaction = models.Transaction(
            owner_username = self.username,
            description = description,
            original_description = original_description,
            amount = self.args['amount'],
            currency = currency,
            date = date
        )
        db.session.add(transaction)

        # Next, create the links from the transaction to its accounts
        if 'accounts' in self.args:
            accounts = json.loads(self.args['accounts'])
            for accountdata in accounts:
                transaction_accounts = []
                if 'amount' in accountdata:
                    # If no amount is specified, do not associate the account
                    accountobject = models.Account.query.options(
                        db.joinedload(models.Account.account_owners)
                    ).filter(
                        db.and_(
                           models.Account.id == accountdata['account'],
                           models.AccountOwner.owner_username == self.username,
                        )
                    ).first()
                    if accountobject:
                        ta = models.TransactionAccount(
                                transaction = transaction,
                                account = accountobject,
                                amount = accountdata['amount'],
                                verified = False
                        )
                        db.session.add(ta)
                    self.add_to_response('accountbalance',
                                         accountdata['account'])
            self.add_to_response('totalbalance')

        # Next, create the links from the transaction to its categories
        if 'categories' in self.args:
            categories = json.loads(self.args['categories'])
            for categorydata in categories:
                transaction_categories = []
                if 'transaction_amount' in categorydata and \
                   'category_amount' in categorydata:
                    # If no amount is specified, do not associate the category
                    categoryobject = models.Category.query.options(
                        db.joinedload(models.Category.currency)
                    ).filter(
                        db.and_(
                            models.Category.id == categorydata['category'],
                            models.Category.owner_username == self.username,
                        )
                    ).first()
                    if categoryobject:
                        tc = models.TransactionCategory(
                                transaction = transaction,
                                category = categoryobject,
                       transaction_amount = categorydata['transaction_amount'],
                              category_amount = categorydata['category_amount']
                        )
                        db.session.add(tc)
                    self.add_to_response('categoriesbalance',
                                         categorydata['category'])

        # Commit everything...
        db.session.commit()
        return transaction.as_dict(self.username)
Пример #17
0
    def update(self, transactionid):
        transaction = self.__own_transaction(transactionid)
        if not transaction:
            self.notfound(
           'Nonexistent transaction cannot be modified (or you do not own it)')

        # First, modifications on the Transaction object itself
        if 'description' in self.args:
            desc = self.args['description']
            if desc.strip() == '':
                transaction.description = transaction.original_description
            else:
                transaction.description = desc
        if 'amount' in self.args:
            transaction.amount = self.args['amount']
        if 'currency' in self.args:
            currency = core.Currency.query.filter(
                db.and_(
                    core.Currency.isocode == self.args['currency'],
                    db.or_(
                        core.Currency.owner_username == self.username,
                        core.Currency.owner_username == None
                    )
                )
            ).first()
            if currency:
                transaction.currency = currency
        if 'date' in self.args:
            date = helpers.date_from_string(self.args['date'])
            if date:
                transaction.date = date

        # Next, update accounts
        if 'accounts' in self.args:
            existing_accounts = dict([ta.as_tuple() for ta in
                                      transaction.transaction_accounts])
            new_accounts_data = json.loads(self.args['accounts'])
            for account_data in new_accounts_data:
                if 'amount' in account_data and 'account' in account_data:
                    amount = account_data['amount']
                    accountid = account_data['account']
                    if accountid in existing_accounts.keys():
                        # Account already linked...
                        if existing_accounts[accountid] != amount:
                            # ...but the amount is different
                            ta = models.TransactionAccount.query.filter(db.and_(
                          models.TransactionAccount.transaction == transaction,
                          models.TransactionAccount.account_id == accountid
                            )).one()
                            ta.amount = amount
                            ta.verified = False
                            self.add_to_response('accountbalance', accountid)
                        existing_accounts.pop(accountid)
                    else:
                        # Account is not already linked
                        # Verify the account is owned by the user
                        accountobject = models.Account.query.options(
                            db.joinedload(models.Account.account_owners)
                        ).filter(
                          db.and_(
                            models.Account.id == accountid,
                            models.AccountOwner.owner_username == self.username
                         )
                        ).first()
                        if accountobject:
                            ta = models.TransactionAccount(
                                    transaction = transaction,
                                    account = accountobject,
                                    amount = amount,
                                    verified = False
                            )
                            self.add_to_response('accountbalance', accountid)
                            db.session.add(ta)
            # All accounts to keep have been poped out from "existing_accounts"
            # Delete all links remaining from this transaction to accounts
            for accountid in existing_accounts.keys():
                ta = models.TransactionAccount.query.filter(db.and_(
                    models.TransactionAccount.transaction == transaction,
                    models.TransactionAccount.account_id == accountid
                )).one()
                self.add_to_response('accountbalance', accountid)
                db.session.delete(ta)

            self.add_to_response('totalbalance')

        # Then, update categories
        if 'categories' in self.args:
            existing_categories = dict([tc.as_tuple() for tc in
                                        transaction.transaction_categories])
            new_categories_data = json.loads(self.args['categories'])
            for category_data in new_categories_data:
                if 'transaction_amount' in category_data and \
                   'category_amount' in category_data and \
                   'category' in category_data:
                    transaction_amount = category_data['transaction_amount']
                    category_amount = category_data['category_amount']
                    categoryid = category_data['category']
                    if categoryid in existing_categories.keys():
                        # Category already linked...
                        if existing_categories[categoryid]['category_amount'] \
                           != category_amount:
                            # ...but the amount is different
                            tc = models.TransactionCategory.query.filter(db.and_(
                         models.TransactionCategory.transaction == transaction,
                         models.TransactionCategory.category_id == categoryid
                            )).one()
                            tc.transaction_amount = transaction_amount
                            tc.category_amount = category_amount
                            tc.verified = False
                            self.add_to_response('categoriesbalance',
                                                 categoryid)
                        existing_categories.pop(categoryid)
                    else:
                        # Category is not already linked
                        # Verify the category is owned by the user
                        categoryobject = models.Category.query.filter(
                          db.and_(
                           models.Category.id == categoryid,
                           models.Category.owner_username == self.username
                         )
                        ).first()
                        if categoryobject:
                            tc = models.TransactionCategory(
                                    transaction = transaction,
                                    category = categoryobject,
                                    transaction_amount = transaction_amount,
                                    category_amount = category_amount
                            )
                            self.add_to_response('categoriesbalance',
                                                 categoryid)
                            db.session.add(tc)
            # All categories to keep have been poped out from
            # "existing_categories"
            # Delete all links remaining from this transaction to categories
            for categoryid in existing_categories.keys():
                tc = models.TransactionCategory.query.filter(db.and_(
                    models.TransactionCategory.transaction == transaction,
                    models.TransactionCategory.category_id == categoryid
                )).one()
                self.add_to_response('categoriesbalance', categoryid)
                db.session.delete(tc)

        db.session.commit()
        return transaction.as_dict(self.username)