/ aws

Spensive: Automation with iOS Workflow & AWS

With Cloudreach .create(v3.0) around the corner and not being able to attend this time due to being on holiday (Sorry, I do choose sitting by the pool in the sun over a Hackathon), I have had the itch to work on a new personal project.

I hate submitting expenses. If you have read my previous blog posts, you'll know this already as I have already tried to tackle this problem using Monzo and some AWS processing.

Since working on that project and using it daily when travelling for work, I have changed from using Monzo for expenses to a more rewarding AMEX Credit Card. Although the service from AMEX is great, not-surprisingly they don't have any easy dev access to user transactions. To solve this, I had to think a bit differently which leads me to Spensive

Spensive is what I am calling my Expenses 2.0 project - It has been built using:

  • iOS Workflow: A really powerful and understated app that allows you to create scripts using visual programming. More on this later
  • AWS Lambda: A simplified approach from Monz - Lambda is used as my expense processor and is split out into a few functions.
  • AWS Step Functions: I have been interested in using StepFunctions for a while and thought this project would be a good chance to have a go.
  • AWS API Gateway: The entry point into Spensive
  • AWS SNS: Notify me when an expense has bene uploaded
  • AWS KMS: Keep everything secure!

Workflow (iOS)

I first heard about Workflow a little while ago when I read that Apple had acquired it and I thought "That sounds cool, but it's probably pretty limited", I downloaded the app to see what it could do and I was left amazed at how much it can do.

Basically, Workflow is a scripting app similar to Scratch but integrates really well with iOS API's as well as various 3rd parties. It allows you to perform some pretty cool things and you can configure how it can be launched - This might be in the form of a widget on your Lock screen, a Share sheet action or even an Apple Watch complication! Once you decide how you launch your Workflow, you are then free to play with various "blocks" that perform different actions.

These blocks can be placed in any order. Most have customisation options and the ability to take input and pass output to the next block - For example, you could place an "Ask for User Input" block which passes the input text to an "Alert" block - This block can have a configured message which includes a variable for the passed input. A simple example but the key to the power of workflow - Its simplicity.

Using Workflow in Spensive

Taking the concepts from Workflow, I created a workflow called Upload Expense. It accepts an image as input (The receipt) and is activated from the share sheet - This means any picture that has the iOS share symbol can be passed into the workflow.

Next, I ask for user input to provide expense information in the form of
<project>-£<price>-<description> which is then passed to a regex block to split out each part into Project, Price & Description

^([0-9]{3})-\£([0-9]{1,3}\.[0-9]{0,2})-(.*)$ # Example: 117-£14.00-Lunch at Costa

After getting the input and assigning each part to a variable, I then build up a dictionary that I can pass as POST input to my API Gateway, upload the receipt image to somewhere I can access later and then send my data to AWS.
Workflow in action
Workflow in action. again
This is where Workflow passes the torch to AWS Lambda and AWS StepFunctions

Processing with AWS Lambda & StepFunctions

AWS Lambda plays the part of processing within Spensive. It will check the input, see if the project provided is valid and create an expense in Financial Force, then it will download the receipt image, upload to Financial force and attach it to the expense. Eventually, if everything has worked, a Lambda function will trigger a publish to SNS to let me know my submission was successful.

SNS Notification

StepFunctions plays a key part in all of this and is responsible for orchestrating each phase of the process.
AWS StepFunctions

The way StepFunctions works is through the use of States. A state is a step that can perform a task - Such as run a Lambda Function (Task state), make a decision on input (Choice State), run two tasks at the same time (Parallel State). You also have (amongst others) Pass, Fail and Retry states. You write your State machine in JSON which when uploaded to AWS, can be viewed visually and shows each of the steps.

In this case, Spensive has the following states:

  • CreateExpense: This was a Task state which runs AWS Lambda to create the expense. It takes input from a Process function which API Gateway triggers.
  • CheckExpense: Create expense returns a {"success":true/false} which is passed to CheckExpense. CheckExpense is a Choice state and checks if success is true or false. if it is true, it runs the ImageUpload step
  • ImageUpload: Another Task state. ImageUpload takes expense information passed from CreateExpense. It will download the image and upload it to the expense.
  • CheckImage: Similar to CheckExpense, It will run Notify if success is true or fail if not.

You can read more about StepFunction's state language here and more about StepFunctions in general here

End result

All of these components together provides me with a super easy way to upload expenses. I don't need to deal with manual input of each field in Financial Force and the time it takes me to upload an expense goes from 2 or 3 minutes each to 15 seconds. Multiply that by 15 expenses per week and the time saving is quickly much higher!

With the way I have developed Spensive and used StepFunctions, It is much easier to expand on its features. I'd like to add in some AWS Rekognition (check out my post about it) to scan the image and also deal with some more of the StepFunction states such as Parallel State which would let me run Rekognition against an image whilst it is uploading to Financial force and then simply update the appropriate field of the Expense rather than having to wait for all processing to complete before uploading it - More time saving! I'd be interested to hear suggestions on how else this could be expanded further, Let me know in the comments below!

Keep it Cloudy!

Neil Stewart

Neil Stewart

Cloud Systems Developer at Cloudreach. Passion for DevOps and Cloud Infrastructure development. AWS Certified in 5 areas and working towards Chef certification. Apple lover and general tech enthusiast

Read More