def add_account_menu(): menu_title("Add account") while 1: print('------') print('Notice') print('------') print('You are about to search for bank connection information') print('on a third party website. This means you are trusting') print('http://ofxhome.com and their security policies.') print('') print('You will be sending your bank name to this website.') print('------') query = prompt('bank name eg. "express" (enter to exit)> ') if query.lower() in ['']: return found = OFXHome.search(query) if not found: error("No banks found") continue while 1: for idx, bank in enumerate(found): menu_item(idx, bank['name']) choice = prompt().lower() if choice in ['q', '']: return elif int(choice) < len(found): bank = OFXHome.lookup(found[int(choice)]['id']) if login_check_menu(bank): return
def add_account_menu(args): menu_title("Add account") while 1: print("------") print("Notice") print("------") print("You are about to search for bank connection information") print("on a third party website. This means you are trusting") print("http://ofxhome.com and their security policies.") print("") print("You will be sending your bank name to this website.") print("------") query = prompt('bank name eg. "express" (enter to exit)> ') if query.lower() in [""]: return found = OFXHome.search(query) if not found: error("No banks found") continue while 1: for idx, bank in enumerate(found): menu_item(idx, bank["name"]) choice = prompt().lower() if choice in ["q", ""]: return elif int(choice) < len(found): bank = OFXHome.lookup(found[int(choice)]["id"]) if login_check_menu(bank, args): return
def add_account_menu(args): menu_title("Add account") while 1: print('------') print('Notice') print('------') print('You are about to search for bank connection information') print('on a third party website. This means you are trusting') print('http://ofxhome.com and their security policies.') print('') print('You will be sending your bank name to this website.') print('------') query = prompt('bank name eg. "express" (enter to exit)> ') if query.lower() in ['']: return found = OFXHome.search(query) if not found: error("No banks found") continue while 1: for idx, bank in enumerate(found): menu_item(idx, bank['name']) choice = prompt().lower() if choice in ['q', '']: return elif int(choice) < len(found): bank = OFXHome.lookup(found[int(choice)]['id']) if login_check_menu(bank, args): return
def add_bank(self, id=None, username=None, password=None): cherrypy.response.headers['Content-Type'] = 'application/json' cherrypy.response.status = 200 result = {'status': 'ok', 'message': ''} if id and username and password: bank = OFXHome.lookup(id) i = Institution(id=bank['fid'], org=bank['org'], url=bank['url'], broker_id=bank['brokerid'], description=bank['name'], username=username, password=password) try: i.authenticate() except Exception as e: result['status'] = 'error' result[ 'message'] = 'unable to log into bank with those credentials' for a in i.accounts(): GlobalConfig.add_account(a) GlobalConfig.save() else: result['status'] = 'error' result['message'] = 'id, username, and password are all required' ret = json.dumps(result) cherrypy.response.body = ret if result['status'] == 'error': cherrypy.response.status = 400 return ret
def bank_config(guid): if bank_config_cache.has_key(guid): return bank_config_cache[guid] path = os.path.join( Settings.fi_cache(), '%s.xml' % guid ) if not os.path.exists(path) or os.path.getsize(path) == 0: logging.info("uncached bank config %s" % guid) institution = OFXHome.lookup(guid) file = open(path,'w') file.write(institution.xml) file.close() logging.info("parsing file %s" % path) bank_config_cache[guid] = OFXHomeInstitution.from_file(path).__dict__ return bank_config_cache[guid]
def add_account_menu(): menu_title("Add account") while 1: query = prompt('enter part of a bank name eg. express> ') if query.lower() in ['']: return found = OFXHome.search(query) if not found: error("No banks found") continue while 1: for idx, bank in enumerate(found): menu_item(idx, bank['name']) choice = prompt().lower() if choice in ['q', '']: return elif int(choice) < len(found): bank = OFXHome.lookup(found[int(choice)]['id']) if login_check_menu(bank): return
def add(request, id): inst = Institution() if request.method == "GET": if id: info = OFXHome.lookup(int(id)) inst.name = info.name inst.fid = info.fid inst.org = info.org inst.url = info.url inst.clean() form = InstitutionForm(instance=inst) else: pass elif request.method == "POST": form = InstitutionForm(data=request.POST, instance=inst) if form.is_valid(): form.save() return HttpResponseRedirect(reverse(show, args=(inst.pk,))) else: request.user.message_set.create(message='Please check your data.') return render(request, "institutions/add.html", {"inst_form": form})
def add_bank(self,id=None,username=None,password=None): cherrypy.response.headers['Content-Type'] = 'application/json' cherrypy.response.status = 200 result = { 'status': 'ok', 'message': '' } if id and username and password: bank = OFXHome.lookup(id) i = Institution( id = bank['fid'], org = bank['org'], url = bank['url'], broker_id = bank['brokerid'], description = bank['name'], username = username, password = password ) try: i.authenticate() except Exception as e: result['status'] = 'error' result['message'] = 'unable to log into bank with those credentials' for a in i.accounts(): GlobalConfig.add_account(a) GlobalConfig.save() else: result['status'] = 'error' result['message'] = 'id, username, and password are all required' ret = json.dumps(result) cherrypy.response.body = ret if result['status'] == 'error': cherrypy.response.status = 400 return ret
def lambda_func(event, context=None): beginf = time.time() query = event['body'] gettimes = [] cmdtimes = [] result = {} if not event['headers'].has_key('Authorization'): result['error'] = "Missing Auth Header" return result token_header_parts = event['headers']['Authorization'].split(" ") if len(token_header_parts) != 2 or token_header_parts[0] != "Bearer": result['error'] = "Malformed Auth Header" return result token_string = token_header_parts[1] headers = jwt.get_unverified_headers(token_string) kid = headers['kid'] key_index = -1 for i in range(len(JWT_KEYS)): if kid == JWT_KEYS[i]['kid']: key_index = i break if key_index == -1: result['error'] = 'Public key not found' return result try: decode = jwt.decode(token_string, JWT_KEYS[key_index], algorithms=['RS256'], issuer=JWT_ISSUER) except: result['error'] = "Not Authorized" return result if query['query'] == 'getfile': filename = os.path.split(query['filename'])[-1] if filename.startswith('online'): begin = time.time() result['contents'] = get_file_from_s3(filename, query["creds"]) end = time.time() gettimes.append(end - begin) else: result['error'] = "Filenames must begin with online" elif query['query'] == 'savefile': filename = os.path.split(query['filename'])[-1] if filename.startswith('online'): try: save_file_to_s3(filename, query['contents'], query["creds"]) result['success'] = True except: result['success'] = False else: result['error'] = "Filenames must begin with online" elif query['query'] == 'report': command = None if query.has_key('name'): reportType = None historical = "auto" if query.has_key('historical'): historical = query['historical'] if query['name'] == "accounts": command = ["hledger", "-I", "-f", "-", "accounts"] reportType = "accounts" elif query['name'] == "budget": command = ["hledger", "-I", "-f", "-", "accounts"] reportType = "budget" else: if query['name'] == "balance": command = [ "hledger", "-f", "-", "balance", "--tree", "-O", "csv" ] reportType = "balance" if historical == "includehistorical": command.append('-H') historical = None elif query['name'] == "register" or query[ 'name'] == "budgetregister" or query[ 'name'] == "combinedregister": if query['name'] == "combinedregister": command = [ "hledger", "-I", "-f", "-", "register", "-O", "csv" ] else: command = [ "hledger", "-f", "-", "register", "-O", "csv" ] if historical == "auto" or historical == "includehistorical": command.append('-H') historical = None reportType = query['name'] if command and query.has_key('time'): command.append('-p') command.append(query['time']) if command and query.has_key('timeperiod'): if query['timeperiod'] in [ 'monthly', 'weekly', 'yearly', 'quarterly', 'daily' ]: command.append('--' + query['timeperiod']) if command and query.has_key('accounts'): parts = query['accounts'].split('_') if len(parts) > 1 and parts[1]: command.append('^' + parts[1]) if historical == "auto" and ( (parts[1].startswith('Assets:') or parts[1].startswith('Liabailities:'))): command.append('-H') else: if parts[0] == "expenses": command.append('^Expenses:') elif parts[0] == "income": command.append('^Income:') elif parts[0] == "incomeexpenses": command.append('^Income:|^Expenses:') elif parts[0] == "assets": command.append('^Assets:') if historical == "auto": command.append('-H') elif parts[0] == "assetssummary": command.append('^Assets:') command.append('--depth') command.append('2') if historical == "auto": command.append('-H') elif parts[0] == "liabilities": command.append('^Liabilities:') if historical == "auto": command.append('-H') elif parts[0] == "assetsliabilities": command.append('^Assets:|^Liabilities:') if historical == "auto": command.append('-H') if command: if reportType == "budget" or reportType == "accounts" or reportType == "combinedregister": begin = time.time() defaultledger = get_file_from_s3("online.ledger", query["creds"]) end = time.time() gettimes.append(end - begin) begin = time.time() budgetledger = get_file_from_s3("onlinebudget.ledger", query["creds"]) end = time.time() gettimes.append(end - begin) begin = time.time() output, errors = subprocess.Popen( command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=launch_env).communicate(defaultledger + os.linesep + budgetledger) end = time.time() cmdtimes.append(end - begin) elif reportType == "budgetregister": begin = time.time() budgetledger = get_file_from_s3("onlinebudget.ledger", query["creds"]) end = time.time() gettimes.append(end - begin) begin = time.time() output, errors = subprocess.Popen( command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=launch_env).communicate(budgetledger) end = time.time() cmdtimes.append(end - begin) else: begin = time.time() defaultledger = get_file_from_s3("online.ledger", query["creds"]) end = time.time() gettimes.append(end - begin) begin = time.time() output, errors = subprocess.Popen( command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=launch_env).communicate(defaultledger) end = time.time() cmdtimes.append(end - begin) if errors: result["error"] = "Report failed: " + errors else: try: items = [] if reportType == "accounts": result = {"result": output.splitlines()} elif reportType == "budget": allaccounts = output.splitlines() transactionfilter = '^' + '$|^'.join( filter( lambda aname: aname.find("Off-Budget") < 0 and not aname.startswith("Expenses:") and not aname .startswith("Income:") and not aname. startswith("Equity:"), allaccounts)) + '$' # Filter and get rid of asset accounts that are part of the budget allaccounts = filter( lambda aname: aname.find("Off-Budget") >= 0 or not aname.startswith("Assets:"), allaccounts) command = [ "hledger", "-I", "-f", "-", "print", transactionfilter ] begin = time.time() filteredledger, errors = subprocess.Popen( command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=launch_env).communicate(defaultledger) end = time.time() cmdtimes.append(end - begin) # Budget report involves 3 reports with various inputs command = [ "hledger", "-I", "-f", "-", "balance", "--tree", "-O", "csv", "-E", "-p", query.get('time', ['thismonth']) ] if query.has_key( 'budgetperiod') and query['budgetperiod'] in [ 'monthly', 'weekly', 'yearly', 'quarterly', 'daily' ]: command.append('--' + query['budgetperiod']) else: command.append('--monthly') begin = time.time() budgetoutput, errors = subprocess.Popen( command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=launch_env).communicate(budgetledger) end = time.time() cmdtimes.append(end - begin) if errors: result["error"] = "Budget report failed: " + errors else: command = [ "hledger", "-f", "-", "balance", "--tree", "-O", "csv", "-E", "-p", query.get('time', ['thismonth']) ] if query.has_key( 'timeperiod') and query['timeperiod'] in [ 'monthly', 'weekly', 'yearly', 'quarterly', 'daily' ]: command.append('--' + query['timeperiod']) else: command.append('--monthly') begin = time.time() spendingoutput, errors = subprocess.Popen( command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=launch_env).communicate(filteredledger) end = time.time() cmdtimes.append(end - begin) if errors: result[ "error"] = "Budget spending report failed: " + errors else: command = [ "hledger", "-I", "-f", "-", "balance", "--tree", "-O", "csv", "-E", "-H", "-p", query.get('time', ['thismonth']) ] if query.has_key('timeperiod' ) and query['timeperiod'] in [ 'monthly', 'weekly', 'yearly', 'quarterly', 'daily' ]: command.append('--' + query['timeperiod']) else: command.append('--monthly') begin = time.time() balanceoutput, errors = subprocess.Popen( command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=launch_env).communicate( filteredledger + os.linesep + budgetledger) end = time.time() cmdtimes.append(end - begin) if errors: result[ "error"] = "Budget balance report failed: " + errors else: budgetitems = {} spendingitems = {} balanceitems = {} reader = csv.DictReader( StringIO.StringIO(budgetoutput)) budgetcolumns = [] reportcolumns = [] columns = [] foundbudgetkeys = False foundspendingkeys = False foundbalancekeys = False for row in reader: if row['Account'] != "total": if not foundbudgetkeys: for col in row.keys(): fixedcol = fix_column_name( col) if fixedcol[0].isdigit( ) and fixedcol not in budgetcolumns: budgetcolumns.append( fixedcol) columns.append( (fixedcol, 0, "Budget " + fixedcol, col)) foundbudgetkeys = True budgetitems[row['Account']] = row reader = csv.DictReader( StringIO.StringIO(spendingoutput)) for row in reader: if row['Account'] != "total": if not foundspendingkeys: for col in row.keys(): fixedcol = fix_column_name( col) if fixedcol[0].isdigit( ) and fixedcol not in reportcolumns: reportcolumns.append( fixedcol) columns.append( (fixedcol, 1, "Actual " + fixedcol, col)) columns.append( (fixedcol, 2, "Balance " + fixedcol, col)) foundspendingkeys = True spendingitems[row['Account']] = row reader = csv.DictReader( StringIO.StringIO(balanceoutput)) for row in reader: if row['Account'] != "total": if not foundbalancekeys: for col in row.keys(): fixedcol = fix_column_name( col) if col[0].isdigit( ) and fixedcol not in reportcolumns: reportcolumns.append( fixedcol) columns.append( (fixedcol, 1, "Actual " + fixedcol, col)) columns.append( (fixedcol, 2, "Balance " + fixedcol, col)) foundbalancekeys = True balanceitems[row['Account']] = row # Now assemble header row header = ['account'] columns.sort() firstbudget = -1 firstbudgetidx = 0 for col, order, colname, lookupcol in columns: if firstbudget < 0: if order == 0: firstbudget = firstbudgetidx else: firstbudgetidx += 1 continue header.append(colname) if firstbudgetidx >= 0: columns = columns[firstbudgetidx:] # Now assemble report rows totals = {'account': 'Total'} for acct in allaccounts: if budgetitems.has_key( acct) or spendingitems.has_key( acct ) or balanceitems.has_key( acct): row = {'account': acct} for col, order, colname, lookupcol in columns: if order == 0: # Budget column if budgetitems.has_key( acct ) and budgetitems[ acct].has_key( lookupcol): row[colname] = negateamount( budgetitems[acct] [lookupcol]) else: row[colname] = "0" elif order == 1: # Actual column if spendingitems.has_key( acct ) and spendingitems[ acct].has_key( lookupcol): row[colname] = negateamount( spendingitems[acct] [lookupcol]) else: row[colname] = "0" elif order == 2: # Balance column if balanceitems.has_key( acct ) and balanceitems[ acct].has_key( lookupcol): row[colname] = negateamount( balanceitems[acct] [lookupcol]) else: row[colname] = "0" aggregate_total( totals, colname, row[colname]) keeprow = False if row['account'].startswith( 'Expenses:' ) or row['account'].startswith( 'Income:' ) or row['account'].startswith( 'Assets:'): keeprow = True for colname in row.keys(): if colname != 'account' and row[ colname] != '0': keeprow = True if keeprow: items.append(row) items.append(totals) result["headers"] = header result["result"] = items else: reader = csv.DictReader(StringIO.StringIO(output)) for row in reader: if reportType == "budgetregister" or reportType == "combinedregister": for k in row.keys(): if k != "txnidx" and k != "date" and k != "description" and k != "account": row[k] = negateamount(row[k]) items.append(row) result["headers"] = reader.fieldnames result["result"] = items except: result[ "error"] = "Report failed to produce readable results" else: result["error"] = "Bad report parameters" elif query['query'] == 'validate': options = ["-I"] if query.has_key('assertions') and query['assertions']: options = [] command = ["hledger", "-f", "-"] + options + ["print"] ledger = query['contents'] begin = time.time() validateoutput, errors = subprocess.Popen( command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=launch_env).communicate(ledger) end = time.time() cmdtimes.append(end - begin) if validateoutput: result["output"] = validateoutput if errors: result["error"] = errors elif query['query'] == 'parseofx': ofxdata = query['contents'] parser = OfxParser.parse(StringIO.StringIO(ofxdata)) convdate = lambda d: ("%0.4d/%0.2d/%0.2d" % (d.year, d.month, d.day) ) if d is not None and hasattr(d, 'year' ) else None strifnotnone = lambda s: str(s) if s is not None else s result["ofxaccounts"] = [{ "fid": getattr(account.institution, "fid", None), "organization": getattr(account.institution, "organization", None), "account_id": getattr(account, "account_id", None), "number": getattr(account, "number", None), "routing_number": getattr(account, "routing_number", None), "type": getattr(account, "type", None), "account_type": getattr(account, "account_type", None), "statement": { "available_balance": strifnotnone( getattr(account.statement, "available_balance", None)), "available_balance_date": convdate( getattr(account.statement, "available_balance_date", None)), "balance": strifnotnone(getattr(account.statement, "balance", None)), "balance_date": convdate(getattr(account.statement, "balance_date", None)), "start_date": convdate(getattr(account.statement, "start_date", None)), "end_date": convdate(getattr(account.statement, "end_date", None)), "currency": getattr(account.statement, "currency", None), "transactions": [{ "amount": strifnotnone(txn.amount), "checknum": getattr(txn, "checknum", None), "date": convdate(getattr(txn, "date", None)), "id": getattr(txn, "id", None), "mcc": getattr(txn, "mcc", None), "memo": getattr(txn, "memo", None), "payee": getattr(txn, "payee", None), "sic": getattr(txn, "sic", None), "type": getattr(txn, "type", None) } for txn in account.statement.transactions] } } for account in parser.accounts] elif query['query'] == 'downloadofx': try: # config = ConfigParser.ConfigParser() # config.readfp(StringIO.StringIO(query['ofxconfig'])) # ofxclient.config.unflatten_dict(dict(config.items(config.sections()[0]))) # acct = ofxclient.account.Account.deserialize(ofxclient.config.unflatten_dict(dict(config.items(config.sections()[0])))) acct = ofxclient.account.Account.deserialize(query['ofxconfig']) dat = acct.download() result["contents"] = dat.read() except Exception as ex: result["error"] = str(ex) elif query['query'] == 'searchofxhome': try: result["result"] = list(OFXHome.search(query['search'])) except Exception as ex: result["error"] = str(ex) elif query['query'] == 'getofxaccounts': try: version = DEFAULT_OFX_VERSION if query.has_key('ofx_version'): version = int(query['ofx_version']) bank_info = OFXHome.lookup(query['ofxhomeid']) if bank_info: i = Institution(id=bank_info['fid'], org=bank_info['org'], url=bank_info['url'], broker_id=bank_info['brokerid'], description=bank_info['name'], username=query['username'], password=query['password'], client_args=ofxclient.cli.client_args_for_bank( bank_info, version)) failed = False try: i.authenticate() except Exception as ex: failed = True result["error"] = "Authentication failed: " + str(ex) if not failed: accts = i.accounts() result["result"] = [acct.serialize() for acct in accts] else: result["error"] = "Could not find bank" except Exception as ex: result["error"] = "Failure: " + str(ex) else: result["error"] = "Bad query" endf = time.time() result["log"] = { "totaltime": (endf - beginf), "gettimes": gettimes, "cmdtimes": cmdtimes } return result