Ejemplo n.º 1
0
 def __own_transaction(self, transactionid):
     return models.Transaction.query.options(
                       db.joinedload(models.Transaction.currency),
                       db.joinedload(models.Transaction.transaction_accounts),
                       db.joinedload(models.Transaction.transaction_categories)
            ).filter(
                 db.and_(
                     models.Transaction.owner_username == self.username,
                     models.Transaction.id == transactionid
                 )
            ).first()
Ejemplo n.º 2
0
 def balance(self, username):
     """
     Return a list :
         [ <balance in account currency>, <balance in preferred currency> ]
     """
     balance = db.session.query(
         db.func.sum(TransactionAccount.amount)
     ).filter(
         TransactionAccount.account_id == self.id
     ).one()[0]
     if balance:
         balances = [ self.start_balance + balance ]
     else:
         balances = [ self.start_balance ]
     balances.append(
         helpers.rate(
             username,
             self.currency.isocode,
             coremodels.User.query.options(
                 db.joinedload(coremodels.User.preferred_currency)
             ).get(
                 username
             ).preferred_currency.isocode
         ) * balances[0]
     )
     return balances
Ejemplo n.º 3
0
Archivo: user.py Proyecto: vadosl/ospfm
 def list(self):
     contacts = models.UserContact.query.options(
                     db.joinedload(models.UserContact.contact)
     ).filter(
                     models.UserContact.user_username == self.username
     )
     return [c.as_dict() for c in contacts.all()]
Ejemplo n.º 4
0
 def list(self):
     categories = models.Category.query.order_by(
         models.Category.name).options(
             db.joinedload(models.Category.currency)).filter(
                 db.and_(models.Category.owner_username == self.username,
                         models.Category.parent_id == None)).all()
     return [c.as_dict(self.username) for c in categories]
Ejemplo n.º 5
0
def totalbalance(username):
    accounts = models.Account.query.options(
        db.joinedload(models.Account.currency)).join(
            models.AccountOwner).filter(
                models.AccountOwner.owner_username == username).all()
    # Calculate the total balance, in the user's preferred currency
    totalbalance = 0
    totalcurrency = core.User.query.options(
        db.joinedload(
            core.User.preferred_currency)).get(username).preferred_currency
    for account in accounts:
        totalbalance += account.balance(username)[0] * \
        helpers.rate(username,
                     account.currency.isocode,
                     totalcurrency.isocode)
    return {'balance': totalbalance, 'currency': totalcurrency.isocode}
Ejemplo n.º 6
0
Archivo: user.py Proyecto: vadosl/ospfm
 def read(self, username):
     if username == 'me' or username == self.username:
         # When requesting his own information, a user gets more details
         user = models.User.query.options(
             db.joinedload(models.User.emails),
             db.joinedload(models.User.preferred_currency)
         ).filter(
             models.User.username == self.username
         ).one()
         return user.as_dict(own=True)
     else:
         user = models.User.query.filter(
             models.User.username == username
         ).first()
         if not user:
             self.notfound('This user does not exist')
         return user.as_dict()
Ejemplo n.º 7
0
 def __own_account(self, accountid):
     return models.Account.query.options(
                     db.joinedload(models.Account.currency)
             ).join(models.AccountOwner).filter(
                 db.and_(
                     models.AccountOwner.owner_username == self.username,
                     models.Account.id == accountid
                 )
             ).first()
Ejemplo n.º 8
0
 def __own_category(self, categoryid):
     return models.Category.query.options(
                     db.joinedload(models.Category.currency)
            ).filter(
                 db.and_(
                     models.Category.owner_username == self.username,
                     models.Category.id == categoryid
                 )
            ).first()
Ejemplo n.º 9
0
def totalbalance(username):
    accounts = models.Account.query.options(
                    db.joinedload(models.Account.currency)
    ).join(models.AccountOwner).filter(
        models.AccountOwner.owner_username == username
    ).all()
    # Calculate the total balance, in the user's preferred currency
    totalbalance = 0
    totalcurrency = core.User.query.options(
                        db.joinedload(core.User.preferred_currency)
                    ).get(username).preferred_currency
    for account in accounts:
        totalbalance += account.balance(username)[0] * \
        helpers.rate(username,
                     account.currency.isocode,
                     totalcurrency.isocode)
    return {
        'balance': totalbalance,
        'currency': totalcurrency.isocode
    }
Ejemplo n.º 10
0
 def list(self):
     categories = models.Category.query.order_by(
                     models.Category.name
                  ).options(
                     db.joinedload(models.Category.currency)
                  ).filter(
                     db.and_(
                         models.Category.owner_username == self.username,
                         models.Category.parent_id == None
                     )
                  ).all()
     return [c.as_dict(self.username) for c in categories]
Ejemplo n.º 11
0
 def balance(self, username):
     """
     Return a list :
         [ <balance in account currency>, <balance in preferred currency> ]
     """
     balance = db.session.query(db.func.sum(
         TransactionAccount.amount)).filter(
             TransactionAccount.account_id == self.id).one()[0]
     if balance:
         balances = [self.start_balance + balance]
     else:
         balances = [self.start_balance]
     balances.append(
         helpers.rate(
             username, self.currency.isocode,
             coremodels.User.query.options(
                 db.joinedload(coremodels.User.preferred_currency)).get(
                     username).preferred_currency.isocode) * balances[0])
     return balances
Ejemplo n.º 12
0
Archivo: user.py Proyecto: vadosl/ospfm
    def update(self, username):
        if username == 'me' or username == self.username:
            # A user can only modify his own information
            user = models.User.query.options(
                db.joinedload(models.User.emails)
            ).filter(
                models.User.username == self.username
            ).one()
            if 'first_name' in self.args:
                user.first_name = self.args['first_name']
            if 'last_name' in self.args:
                user.last_name = self.args['last_name']
            if 'password' in self.args and \
               username not in config.DEMO_ACCOUNTS:
                if 'currentpassword' in self.args and \
                           authentication.authenticate(
                                username,
                                self.args['currentpassword'],
                                False
                           ):
                    if len(self.args['password']) < 8:
                        self.badrequest(
                               'Password should be at least 8 characters long')
                    user.passhash = sha512_crypt.encrypt(
                                        self.args['password'],
                                        rounds=config.PASSWORD_SALT_COMPLEXITY
                                    )
                else:
                    self.badrequest(
                                 "Please provide the correct current password")
            if 'preferred_currency' in self.args:
                currency = models.Currency.query.filter(
                  db.and_(
                     models.Currency.isocode == self.args['preferred_currency'],
                     models.Currency.owner_username == None,
                  )
                ).first()
                if currency:
                    # When preferred currency is changed, all owner's
                    # currencies rates must be changed
                    # XXX Debts amounts should also be changed... when debts will be implemented
                    multiplier = user.preferred_currency
                    multiplier = exchangerate.getrate(
                        user.preferred_currency.isocode,
                        currency.isocode
                    )
                    for c in models.Currency.query.filter(
                        models.Currency.owner_username == self.username
                    ):
                        c.rate = c.rate * multiplier
                    user.preferred_currency = currency
                    self.add_to_response('totalbalance')
            if 'emails' in self.args:
                emails = json.loads(self.args['emails'])
                previous_emails = []
                previous_notifications = []
                for address in models.UserEmail.query.filter(
                              models.UserEmail.user_username == self.username):
                    previous_emails.append(address.email_address)
                    if address.notification:
                        previous_notifications.append(address.email_address)
                if type(emails) == type({}):
                    if 'add' in emails and \
                       type(emails['add']) == type([]) and \
                       username not in config.DEMO_ACCOUNTS:
                        for address in emails['add']:
                            # TODO Verify there is a "@" in the email address
                            if address not in previous_emails:
                                # Use random hash for email confirmation
                                # Email confirmation is done outside of OSPFM
                                # Another process must read the database and
                                # send confirmation emails
                                randomhash = os.urandom(8).encode('hex')
                                db.session.add(
                                    models.UserEmail(
                                        user_username = self.username,
                                        email_address = address,
                                        confirmation = randomhash
                                    )
                                )
                    if 'remove' in emails and type(emails['remove'])==type([]):
                        for address in emails['remove']:
                            if address in previous_emails:
                                db.session.delete(
                                    models.UserEmail.query.filter(
                                        db.and_(
                               models.UserEmail.user_username == self.username,
                               models.UserEmail.email_address == address
                                        )
                                    ).first()
                                )
                    if 'enablenotifications' in emails and \
                       type(emails['enablenotifications']) == type([]):
                        for address in emails['enablenotifications']:
                            if address not in previous_notifications:
                                models.UserEmail.query.filter(
                                    db.and_(
                               models.UserEmail.user_username == self.username,
                               models.UserEmail.email_address == address
                                    )
                                ).first().notification = True
                    if 'disablenotifications' in emails and \
                       type(emails['disablenotifications']) == type([]):
                        for address in emails['disablenotifications']:
                            if address in previous_notifications:
                                models.UserEmail.query.filter(
                                    db.and_(
                               models.UserEmail.user_username == self.username,
                               models.UserEmail.email_address == address
                                    )
                                ).first().notification = False


            db.session.commit()
            return self.read(username)
        else:
            self.forbidden('The only user you can modify is yourself')
Ejemplo n.º 13
0
 def __own_category(self, categoryid):
     return models.Category.query.options(
         db.joinedload(models.Category.currency)).filter(
             db.and_(models.Category.owner_username == self.username,
                     models.Category.id == categoryid)).first()
Ejemplo n.º 14
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)
Ejemplo n.º 15
0
 def __filter(self, filter):
     filters = [
         models.Transaction.owner_username == self.username,
     ]
     limit = 100
     after = False
     for part in filter.items():
         if part[0] in filter_functions:
             filters.extend(
                 filter_functions[part[0]](part[1])
             )
         elif part[0] == 'limit':
             try:
                 limit = min(int(part[1]), 100)
             except:
                 pass
         elif part[0] == 'after':
             try:
                 after = int(part[1])
             except:
                 pass
     if after:
         # Get offset of the "from" transaction
         # XXX: Is there a more efficient way to do so ?
         all_transactions = db.session.query(models.Transaction.id).order_by(
                             db.desc(models.Transaction.date)
                        ).filter(
                             db.and_(
                                 *filters
                             )
                        )
         all_ids = [t.id for t in all_transactions]
         try:
             offset = all_ids.index(after) + 1
         except:
             offset = 0
         transactions = models.Transaction.query.options(
                     db.joinedload(models.Transaction.currency),
                     db.joinedload(models.Transaction.transaction_accounts),
                     db.joinedload(models.Transaction.transaction_categories)
                 ).order_by(
                     db.desc(models.Transaction.date)
                 ).filter(
                     db.and_(
                         *filters
                     )
                 ).offset(offset).limit(limit)
         return [t.as_dict(self.username) for t in transactions]
     else:
         transactions = models.Transaction.query.options(
                     db.joinedload(models.Transaction.currency),
                     db.joinedload(models.Transaction.transaction_accounts),
                     db.joinedload(models.Transaction.transaction_categories)
                 ).order_by(
                     db.desc(models.Transaction.date)
                 ).filter(
                     db.and_(
                         *filters
                     )
                 ).limit(limit)
         return [t.as_dict(self.username) for t in transactions]
Ejemplo n.º 16
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)