diff --git a/starling b/starling index b48d098..b690003 100755 --- a/starling +++ b/starling @@ -223,18 +223,26 @@ class StarlingClient: def payment(self, account_uid, category_uid, data): return self.signed_put(f'payments/local/account/{account_uid}/category/{category_uid}', data, token='payments') + def spaces(self, account_uid): + return self.get(f'account/{account_uid}/spaces') + ### Mid-level methods to munge the data from the low-level calls ### - def formatted_balance(self, account_uid): - balance = self.balance(account_uid).effectiveBalance - if balance.currency == 'GBP': + def get_primary_account(self): + for account in self.accounts().accounts: + if account.accountType == 'PRIMARY': + return account + sys.exit('ERROR: No PRIMARY account found') + + def format_amount(self, amount): + if amount.currency == 'GBP': symbol = '£' - elif balance.currency == 'EUR': + elif amount.currency == 'EUR': symbol = '€' else: - sys.exit(f'ERROR: Unsupported currency {balance.currency}') - major_units = int(balance.minorUnits / 100) - minor_units = balance.minorUnits % 100 + sys.exit(f'ERROR: Unsupported currency {amount.currency}') + major_units = int(amount.minorUnits / 100) + minor_units = amount.minorUnits % 100 return f'{symbol}{major_units}.{minor_units:02d}' ### High-level methods which correspond to actions ### @@ -262,9 +270,9 @@ class StarlingClient: else: print(f'This holder has {count} accounts:') for account in accounts: - balance = self.formatted_balance(account.accountUid) + balance = self.balance(account.accountUid).effectiveBalance print(f' {account.name}:') - print(f' Balance: {balance}') + print(f' Balance: {self.format_amount(balance)}') print(f' Account type: {account.accountType}') print(f' Account UID: {account.accountUid}') print(f' Default category: {account.defaultCategory}') @@ -346,13 +354,7 @@ class StarlingClient: if match is None: sys.exit(f'ERROR: bad amount "{amount}" - must be number with two decimal places') minor_units = (int(match.group(1)) * 100) + int(match.group(2)) - primary = None - for account in self.accounts().accounts: - if account.accountType == 'PRIMARY': - primary = account - break - else: - sys.exit('ERROR: No PRIMARY account found') + account = self.get_primary_account() data = { 'externalIdentifier': str(datetime.datetime.utcnow().timestamp()), 'destinationPayeeAccountUid': payee_uid, @@ -362,9 +364,39 @@ class StarlingClient: 'minorUnits': minor_units, } } - response = self.payment(primary.accountUid, primary.defaultCategory, data) + response = self.payment(account.accountUid, account.defaultCategory, data) print(f'Successfully created payment order with UID {response.paymentOrderUid}') + def list_spaces(self): + account = self.get_primary_account() + result = self.spaces(account.accountUid) + self.print_savings_goals(result.savingsGoals) + self.print_spending_spaces(result.spendingSpaces) + + def print_savings_goals(self, goals): + count = len(goals) + print(f'Account has {count} savings goal(s):') + for index, goal, in enumerate(goals, 1): + print(f'{index}. Savings Goal UID = {goal.savingsGoalUid}') + print(f' Name = {goal.name}') + if hasattr(goal, 'target'): + print(f' Target = {self.format_amount(goal.target)}') + print(f' Total Saved = {self.format_amount(goal.totalSaved)}') + if hasattr(goal, 'savedPercent'): + print(f' Saved Percent = {goal.savedPercent}') + print(f' State = {goal.state}') + + def print_spending_spaces(self, spaces): + count = len(spaces) + print(f'Account has {count} spending space(s):') + for index, space, in enumerate(spaces, 1): + print(f'{index}. Spending Space UID = {space.spaceUid}') + print(f' Name = {space.name}') + print(f' Balance = {self.format_amount(space.balance)}') + print(f' Card Association UID = {space.cardAssociationUid}') + print(f' Type = {space.spendingSpaceType}') + print(f' State = {space.state}') + #-----------------------------------------------------------------------------# parser = argparse.ArgumentParser( @@ -432,6 +464,10 @@ elif action == 'pay': if count > 3: parser.error(f'Too many arguments for "{action}" action') client.pay(*action_args) +elif action == 'spaces': + if count > 1: + parser.error(f'Too many arguments for "{action}" action') + client.list_spaces() else: parser.error(f'Unknown action "{action}"')