Before I started university I worked at a local restaurant where the entire process around the schedule took part on paper. Modifications to the schedule were made by crossing out old start times, availability for all employees was written down on a single physical piece of paper, and hours worked were manually calculated and aggregated through a daily print out of a day-list.
With my experience in building web applications I discussed the option of building a custom scheduling solution for the restaurant with the owner of the restaurant. After some initial sketches and discussion I started work on a prototype. This project was the first real world application that I built for people to use.
The application itself has quite a lot of functionality, but the main features are:
- A virtual schedule editor with publish option (to allow for experimentation in draft mode)
- Employees can indicate their availability, or request time-off through the app. This is immediately visible in the schedule editor.
- A virtual day-list is created automatically from the schedule, any modifications made are immediately visible on the schedule.
- Worked hours can be exported to file or sent to a payrolling service through a custom built integration.
- Employees can exchange their shifts by making a request, the request needs to be approved by a team leader or admin, once accepted the changes are reflectled immediately.
The process
The entire project has been built from the ground up by me, including the design. I gained deep exeprience with different concepts such as authentication, mobile web apps, how to build an API, how to interface with other applications, and how to manage and update state in a frontend VueJS application.
Throughout the development process I worked iteratively with the restaurant owner and, once we had a working prototype, with other employees to test and improve the application.
After completion (version 1.0.0) I maintained the application with several updates where I fixed bugs, implemented the ability for employees to exchange their shifts, and improved performance.
Over the years, developing and maintaining this product, I have learned many valuable lessons. I experienced the concequences of technical debt, the advantages to testing my application, the trade-off between building additional features and the complexity in maintenance, and the architectural cost of certain decisions such as not supporting multi-tenancy at the application layer. In addition to these technical lessons I also worked with the actual users of the product, learned how to translate their requests into designs, iterate upon them, and finally translate the design into working application code.
A highlight
One of the most challenging aspects to implement was the authorization system, after working on the authentication I needed to be able to create different roles for different types of employees. This specific restaurant required 4 roles:
- Admin, has access to everything.
- Team Leader, has access to published schedules only but is able to modify and sign the day list, as well as accepting exchange requests.
- Employee, has access to published schedules only.
- Dashboard, a specific role that is only allowed to see and edit the day-list.
As I planned to launch the system for different restaurants I decided to take a variable route such that I could make changes to the permissions setup on a per-system basis.
I annotated every API function with a required permission that the logged in account needs to be able to use it. This allowed me to define roles, each only with the permissions for the calls they are allowed to make. Employees are assigned a specific role and therefore inherit all the permissions from that role. This system made it easy to add additional roles where needed or to modify them for a different instance of the application.
New Version
As this was the first project I completed at this scale of complexity, I made early mistakes in the architecture of the system. Most importantly the system does not scale easily to multiple restaurants, it requires a separate instance of the application for each different restaurant. While I was able to automate the setup of a new system using Docker it still requires manual work.
In the new version I make use of multi-tenancy, a design pattern that allows the same system to handle separate, software isolated, workspaces for each restaurant.
The new version does not include additional features over the original, instead I am building less, such that the supported features get the attention they deserve. The underlying thought is to build half a product, not a half-asssed product. This is important because I am working on this product by myself, in the hours next to my day job. The time I have is limited, and should be used as effectively as possible.
Additionally the new version is built on top of Ruby on Rails. This has resulted in a much simpler application compared to the previous architecture. The server-side rendered nature of Ruby On Rails eliminates an entire workload from the project, which in turn simplifies the maintanance required in the long run. There is no need to create a client-side data model, handle client side data storage and updating (using a framework like VueX), or to maintain a separate pipeline to build such a frontend application.
In addition, new developments in the world of Rails such as Turbo and Turbo Native have allowed me to easily set up native mobile companion applications, while staying (mostly) in Ruby world.