Tuesday, July 29, 2014

POS Architecture

The initial design proved itself to be working nicely so I've stuck to it:
  • Android tablet in each kiosk connected to the Internet via 3G Wi-Fi router. Tablets with 3G modem are more expensive and every kiosk had already been equipped with 3G Wi-Fi router because of the previous system.
  • HTML SPA (Single Page Application) as client POS application running in the browser on the tablet
  • JavaScript Azure Mobile Services (AMS) with SQL database as server
The software architecture is guided by using Durandal (MVVM design pattern) on the client and AMS on the server. I decided to use Durandal because I like the testability of MVVM applications and AMS because of its easy use.

POS as web page
The whole POS software runs as a HTML5 application in full screen browser. Cashiers cannot use other apps on the tablet because the special tablet holder hides main Android menu, all hardware buttons and prevents edge swiping which is the only way how to control the browser. Here is the picture of the real device:


All AMS endpoints require authenticated user. AMS supports several authentication providers. I've chosen Google provider as all company employees have Google account. Special Google account has been created for every kiosk. The kiosk account is signed in in the POS browser all the time so no cashier needs to know its password.

There are only two groups of users:
  1. Cashiers
    They can only insert data (transactions, shifts)
    . Every cashier has assinged a PIN which is used to start her shift.
  2. Company employees
    Additionally to cashiers, they can also edit some data (cashier management) and read the data (reports). As there are only 3 employees at this moment, their Google ids are hardcoded in scripts.

Offline mode
Because kiosks are connected to the Internet via mobile network, I expected they can be offline from time to time. That’s why every operation is first saved to browser local storage and only when server confirms it is saved in the database, it is deleted from the local storage. When confirmation comes, then next unsaved operation is sent to the server until the queue is empty. Operations are sent one by one to not trigger multiple requests at the same time (imagine sending all transactions from one day at once).

As the launch day approached, I started to wonder/worry how to monitor the health of the kiosks. There is no way to connect to them from the Internet and check the POS status. So I did it other way round. Every POS pings the server in specified interval (10 minutes) and reports its status (signed in cashier, locally stored operations, POS version). Company employees and I have access to the web page which displays statuses of all kiosks. The most important information is whether kiosk is alive (pinging) or dead. Repair is simple - restart tablet and/or router.

Release package
Grunt task for creating release package contains steps to uglify JavaScript and uncss/mincss (uglify for CSS rules). Initially, the Durandal pages were separate files even in the release package but I had to change it (more on that later). Now, the whole POS consists of three files: index.html, index.css, and main.js.

Sunday, July 27, 2014

Development Environment

I took this project as an opportunity to learn recent web development techniques. This is the list of buzz words I've used:

First, I used Bower to download Durandal and Bootstrap and prepared some basic Grunt configuration (run web server for development). Then, I dived into Durandal and learned how to structure the application. I tried to scaffold the app structure with existing Durandal's Grunt configuration but eventually, I created everything from scratch using the scaffolding structure as a tutorial. One learns more with this approach.

Having basic app structure (2 pages wired together) and grunt configuration, I created my first Jasmine test. I wanted to practice TDD for development but I found out that it does not work well for me. I did not have any clear vision how things would work and I did a lot of changes during the development. That's why I have just classic unit tests. Once I am satisfied with a feature, I create unit tests for it to make sure I won't break it in future.

Although Durandal uses AMD, I worried about referencing source files from tests. The research, experimentation and creating Grunt configuration took me some time. But it works nicely in the end. Grunt's Jasmine task references two require.config.js files. The first one is the main application require.config.js file and the second one is Jasmine's one with baseUrl pointing to application's folder. All unit tests run when any of my JavaScript files change.

The last thing to figure out was how to test SQL queries. I set it up only later when I was developing the report and it was obvious that with manual testing I would not be able to cover all the corner cases properly. I use T.S.T. and I set it up like unit tests. I have special query file which contains just the SQL query. Using simple script, this query is inserted into production and testing JavaScript template files. If any of these files change, tests are triggered. Of course, there is a Grunt task for firing it up.

Note at the end: web technologies change rapidly. Today, instead of Durandal, I might use just Knockout 3 based on Steve Sanderson NDC presentation:  Architecting large Single Page Applications with Knockout.js.

Saturday, July 26, 2014

POS for Ice-cream Kiosks

I have a neighbor who sells ice cream. He owns several kiosks in various towns around the country.  Two years ago we talked and he asked how hard would be to develop a simple POS (Point Of Sale) for him. He was very unsatisfied with his solution. He had a general cash register from which he had to download all transactions every day otherwise they would disappear. It had functionality he did not need but also lacked some functionality he needed. And it was expensive.

I worked for Radiant Systems so I know a thing or two about POS systems. This one is very simple. All it has to do is to send transactions to the server. The items and prices are fixed during the year which means there is no inventory management. The only changing variables are cashiers but their management is simple - we need to track just name, pin and kiosk where the cashier work. Reporting consists of one report with sold items and shift durations. Overall, quite simple functionality, right?

Then I started thinking about the server requirements which is a grey area for me. I don't know enough about it, especially about operations. I played with Node in Azure VM a little bit but I was not sure enough. The project went to sleep at the end of the year 2012…

To be resumed a year later. My neighbor was more angry about the cash registers. And there was a new feature in Azure - the Mobile Services. I don't need to deal with the server details any more. Exactly what I wanted. So in the autumn 2013, we agreed on an attempt to implement it and I started to work on a proof of concept.

Following the KISS principle, the initial design was as follows:
  • Android tablet in each kiosk connected to the Internet via 3G modem
  • HTML SPA (Single Page Application) as client POS application running in the browser on the tablet
  • JavaScript Azure Mobile Services with SQL database as server

I prototyped an initial solution during the rest of the year 2013. Three screens (sign in, cash box, report), all in one big awful HTML page. But that is what prototypes are for - to see whether it can work, then throw it away and do it properly. Here is the main screen from the prototype:

We tested it on a tablet and it looked good - a green light for my little, fun, real, side project. I had three months to properly develop it during my spare time. Yes, it was optimistic :-)