Use case idea: ability to search transactions on iphone app

Using the API, would it be possible to search through transactions on a smartphone? Currently this is a big missing feature for me on the iphone app... 

7replies Oldest first
  • Oldest first
  • Newest first
  • Active threads
  • Popular
  • That’s a great idea! You could use Pythonista for that..

    Reply Like
  • Quick example of a full text search with cache:

    # coding: utf-8
    import console, requests, json, datetime
    
    def get_id_for_name(collection, name):
        for item in collection:
            if item['name']==name:
                return item['id']
        raise ValueError('name not found in collection!', name, collection)
    
    def get_initdata():
        try:
            with open("ynab_search_data_file.json") as data_file:
                data = json.load(data_file)
            print('Data loaded. Refreshing.')
    
            fresh_transactions = requests.get('https://api.youneedabudget.com/v1/budgets/' + data['budget_id'] + '/transactions', headers=data['header'], params={'since_date': data['refresh_date']})
            fresh_transactions.raise_for_status()
            fresh_transactions = fresh_transactions.json()['data']['transactions']
    
            merged_transactions = data['txdata_cache'] + fresh_transactions
    
            data = {
                'header': data['header'],
                'refresh_date': datetime.datetime.now().date().isoformat(),
                'budget_id': data['budget_id'],
                'txdata_cache': merged_transactions
            }
            with open("ynab_search_data_file.json", "w") as write_file:
                json.dump(data, write_file)
            return data
    
        except FileNotFoundError:
            print('Data file not found. Getting new data.')
            pa_token = console.input_alert('YNAB Personal Access Token needed')
            header = {'Authorization': 'Bearer ' + pa_token}
    
            budgets = requests.get('https://api.youneedabudget.com/v1/budgets', headers=header)
            budgets.raise_for_status()
            budgets = budgets.json()['data']['budgets']
            budget_id = get_id_for_name(budgets, 'Your Budget name goes here')
    
            transactions = requests.get('https://api.youneedabudget.com/v1/budgets/' + budget_id + '/transactions', headers=header)
            transactions.raise_for_status()
            transactions = transactions.json()['data']['transactions']
    
            data = {
                'header': {
                    'Authorization': 'Bearer ' + pa_token
                },
                'refresh_date': datetime.datetime.now().date().isoformat(),
                'budget_id': budget_id,
                'txdata_cache': transactions
            }
            with open("ynab_search_data_file.json", "w") as write_file:
                json.dump(data, write_file)
    
            return get_initdata()
    
    
    if __name__ == '__main__':
        initdata = get_initdata()
        print('success')
        term = console.input_alert('Searchterm?')
    
        filtered = list(filter(lambda x: (x['category_name'] is not None and term in x['category_name']) or  (x['payee_name'] is not None and term in x['payee_name']) or (x['memo'] is not None and term in x['memo']), initdata['txdata_cache']))
        print(len(filtered), 'found')
        import pprint
        pprint.pprint(filtered)
    
    Reply Like
    • whustedt Thank you! Will take a look at this. I was also thinking about a Swift app... but I am not a Python or Swift developer and so this could be a good experience.

      Reply Like
  • Made a mistake merging cached data with fresh transactions. Improved version:

    # coding: utf-8
    import console, requests, json, datetime
    
    def get_id_for_name(collection, name):
        for item in collection:
            if item['name']==name:
                return item['id']
        raise ValueError('name not found in collection!', name, collection)
    
    def get_initdata():
        try:
            with open("ynab_search_data_file.json") as data_file:
                data = json.load(data_file)
            print('Data loaded. Refreshing.')
    
            fresh_transactions = requests.get('https://api.youneedabudget.com/v1/budgets/' + data['budget_id'] + '/transactions', headers=data['header'], params={'since_date': data['refresh_date']})
            fresh_transactions.raise_for_status()
            fresh_transactions = fresh_transactions.json()['data']['transactions']
    
            tmp_merge_txlist = data['txdata_cache'] + fresh_transactions
    
            merged_transactions = []
            for i in range(len(tmp_merge_txlist)):
                if tmp_merge_txlist[i] not in tmp_merge_txlist[i+1:]:
                    merged_transactions.append(tmp_merge_txlist[i])
    
            data = {
                'header': data['header'],
                'refresh_date': datetime.datetime.now().date().isoformat(),
                'budget_id': data['budget_id'],
                'txdata_cache': merged_transactions
            }
            with open("ynab_search_data_file.json", "w") as write_file:
                json.dump(data, write_file)
            return data
    
        except FileNotFoundError:
            print('Data file not found. Getting new data.')
            pa_token = console.input_alert('YNAB Personal Access Token needed')
            header = {'Authorization': 'Bearer ' + pa_token}
    
            budgets = requests.get('https://api.youneedabudget.com/v1/budgets', headers=header)
            budgets.raise_for_status()
            budgets = budgets.json()['data']['budgets']
            budget_id = get_id_for_name(budgets, 'INSERT_YOUR_BUDGET_NAME_HERE')
    
            transactions = requests.get('https://api.youneedabudget.com/v1/budgets/' + budget_id + '/transactions', headers=header)
            transactions.raise_for_status()
            transactions = transactions.json()['data']['transactions']
    
            data = {
                'header': {
                    'Authorization': 'Bearer ' + pa_token
                },
                'refresh_date': datetime.datetime.now().date().isoformat(),
                'budget_id': budget_id,
                'txdata_cache': transactions
            }
            with open("ynab_search_data_file.json", "w") as write_file:
                json.dump(data, write_file)
    
            return get_initdata()
    
    
    if __name__ == '__main__':
        initdata = get_initdata()
        print('success')
        term = console.input_alert('Searchterm?')
    
        filtered = list(filter(lambda x: (x['category_name'] is not None and term in x['category_name']) or  (x['payee_name'] is not None and term in x['payee_name']) or (x['memo'] is not None and term in x['memo']), initdata['txdata_cache']))
        print(len(filtered), 'found')
        import pprint
        pprint.pprint(filtered)
    
    Reply Like 1
      • whustedt
      • whustedt
      • 8 mths ago
      • Reported - view

      Made several improvements:

      1. Case-insensitive search
      2. Cache will only be refreshed if it is older than a day
      3. Budget can be chosen from a list during initial run. You only need a Personal Access Token to start!
      # coding: utf-8
      import console, dialogs, requests, json, datetime
      
      def get_id_for_name(collection, name):
          for item in collection:
              if item['name']==name:
                  return item['id']
          raise ValueError('name not found in collection!', name, collection)
      
      def get_initdata():
          try:
              with open("ynab_search_data_file.json") as data_file:
                  data = json.load(data_file)
      
              todays_date = datetime.datetime.now().date().isoformat()
              still_fresh = data['refresh_date'] == todays_date
              if data['refresh_date'] == datetime.datetime.now().date().isoformat():
                  print('Data loaded. Fresh enough.')
              else:
                  print('Data loaded. Refreshing.')
                  fresh_transactions = requests.get('https://api.youneedabudget.com/v1/budgets/' + data['budget_id'] + '/transactions', headers=data['header'], params={'since_date': data['refresh_date']})
                  fresh_transactions.raise_for_status()
                  fresh_transactions = fresh_transactions.json()['data']['transactions']
      
                  tmp_merge_txlist = data['txdata_cache'] + fresh_transactions
                  merged_transactions = []
                  for i in range(len(tmp_merge_txlist)):
                      if tmp_merge_txlist[i] not in tmp_merge_txlist[i+1:]:
                          merged_transactions.append(tmp_merge_txlist[i])
      
                  data = {
                      'header': data['header'],
                      'refresh_date': datetime.datetime.now().date().isoformat(),
                      'budget_id': data['budget_id'],
                      'txdata_cache': merged_transactions
                  }
                  with open("ynab_search_data_file.json", "w") as write_file:
                      json.dump(data, write_file)
              return data
      
          except FileNotFoundError:
              print('Data file not found. Getting new data.')
              pa_token = console.input_alert('YNAB Personal Access Token needed')
              header = {'Authorization': 'Bearer ' + pa_token}
      
              budgets = requests.get('https://api.youneedabudget.com/v1/budgets', headers=header)
              budgets.raise_for_status()
              budgets = budgets.json()['data']['budgets']
              budget_name = dialogs.list_dialog('Choose a budget', [budget['name'] for budget in budgets])
              budget_id = get_id_for_name(budgets, budget_name)
      
              transactions = requests.get('https://api.youneedabudget.com/v1/budgets/' + budget_id + '/transactions', headers=header)
              transactions.raise_for_status()
              transactions = transactions.json()['data']['transactions']
      
              data = {
                  'header': {
                      'Authorization': 'Bearer ' + pa_token
                  },
                  'refresh_date': datetime.datetime.now().date().isoformat(),
                  'budget_id': budget_id,
                  'txdata_cache': transactions
              }
              with open("ynab_search_data_file.json", "w") as write_file:
                  json.dump(data, write_file)
      
              return get_initdata()
      
      
      if __name__ == '__main__':
          initdata = get_initdata()
          print('success')
          term = console.input_alert('Searchterm?').casefold()
      
          filtered = list(filter(lambda x: (x['category_name'] is not None and term in x['category_name'].casefold()) or  (x['payee_name'] is not None and term in x['payee_name'].casefold()) or (x['memo'] is not None and term in x['memo'].casefold()), initdata['txdata_cache']))
      
          print(len(filtered), 'found')
          import pprint
          pprint.pprint(filtered)
          
      Reply Like
  • Yes, please make this available! 

    Reply Like
  • I am not albe to Search on iPhone App. I just discovered this Kissinger feature and can’t believe it is true. I am paying my rent +utility bills and I was wondering what have I paid last time to my landlord. Oh well, I was not able to find out this easily. 

    Reply Like
Like3 Follow
  • 3 Likes
  • 6 mths agoLast active
  • 7Replies
  • 567Views
  • 4 Following