Portfolio

Pharmacy - IMPOSS Desktop App

 IMPOSS 3.0 Login Window

IMPOSS (abbreviation for Inventory Management and Point-of-Sales System) is Biomed Pharmacy's advanced Business Management System that uses SvelteKit, Nodejs, NW.js, Prisma, SQLite, and some more technologies that improves how this pharmacy business manage inventory, transactions, and sales reporting for better efficiency and customer service.

It has quite been a journey from the concept of creating this application until now. It all started when a client reached out to me regarding the development of an application to manage the inventory and sales of a pharmacy business. I took up the offer, how complicated can it be, right?

4 years later, an entire application refactor, and 3 failed attempts at refactoring it, here we are. I had to make my own "framework" as at that time, learning one is too complicated for me and I honestly have no idea where to start. This is my journey at how I finished this application.

Initial Development

It all started when my girlfriend's mother wanted their inventory and point-of-sales system to be improved from the honestly really bad software that they use in their pharmacy for their day-to-day use. I think it was written in C++ or some kind of lower-level software language. I can see why they wanted it changed as it does not fit their requirements. There are a lot of untied edges, and it has no station-cashier system as it solely lives on the computer of the cashier. The only real advantage to this software compared to mine is that it's fast and responds quickly to clicks and keyboard shortcuts, but that does not do much when it does not do its job well in the first place.


IMPOSS 1.0

For this one, I was mostly influenced by how portable the old software is and that it only lives in 1 folder with a few required files for it to function. I'm a web developer, not a native desktop application developer, so the first thing that I did was to try to find a way to write desktop software using web technologies and have some desktop features available for me to use, such as no-dialog printing, saving files to the desktop, etc. At first, I experimented a bit on HTA files. Simply rename an HTML file to HTA and this file will now open like a browser but without the address bar and such. I trashed this concept as HTA is a really old technology and I did not want to deal with how old it is. I went back to the drawing board and continued my research.

Note: I tried running the 1.0 version of the application just to get a screenshot but no, it will not run anymore. I found it!

IMPOSS 1.0 Server Window Preview

This is where I encountered branchseer's Deskgap, an open-source native desktop software that taps on the built-in HTML viewer of Windows that can run web technologies natively. At that time, this was still maintained, but just not that often. I was not that knowledgeable with these things back then so I just went on with it and used it. No build steps, no frameworks, nothing. Just a big pile of backend Nodejs paired with a running MySQL Server and a bunch of HTML, JavaScript, and CSS files all bunched up together in a single folder for Deskgap to show to the user. It worked fine for this first iteration, but the lack of maintenance support bit me later on as the crashes kept on happening regularly. Deskgap is quite an unstable software, and after I realized that this software was not gonna get any further maintenance patches, I started looking into different native desktop applications that can run web technologies natively, and this is where I stumbled on NWJS.

IMPOSS 2.0 Login Window Preview

IMPOSS 2.0

It was great. It was a little bit bulky compared to Deskgap's 30 MB footprint; this one is a Chromium browser built to behave like a desktop application. Chromium browsers are quite bulky, so this one is clocking in at around 150-200 MB. I'm not sure why I'm still trying to stick to this notion of making desktop software as small as possible when I can just let it be and have it as is, so I stopped thinking about the file size of the entire software and instead continued experimenting with it. So far, it felt promising, and maintenance support for it still exists, so I committed to it and started my refactoring from Deskgap to NWJS.

So the refactor started happening. The tech stack is still a bit bad but at least it's way better compared to the first one as I actually coded some kind of build step to make the production compilation step a little bit better. I was not yet learning frontend frameworks at that time so HMR is quite new to me at that time. Based on how I coded my build step, my DX is quite bad as after I do some changes, I still need to refresh the page, and worse, I had to restart the entire NWJS application to see my changes reflected as my src folder is separate from my dev folder, where the compiled app lives after seeing changes in the src folder.

Overengineered development compiler

It worked for me, so I went with it. After 4 months of constantly hammering the keyboard, it's finally done. We did a trial run on the store, fixed some bugs along the way during the trial run along with some inconveniences with the UI flow that needed some polishing, and when it was finally done, we deployed it for a full production run.

The tech stack for this application is the same with v1. The only thing that changed is the web application runner, which is NWJS. This is what the implementation looked like.

Implementation of IMPOSS v2

I haven't explained to you a high-level explanation of how the application works. This is what's happening under the hood. We have a NWJS application running in the cashier computer. This app runs two things. First is a MySQL database which handles the transactions, inventory, stocks, and user information. Second, it also runs an ExpressJS server that serves a webserver to the station computers. The NWJS application in the station computers basically act as a web browser accessing the cashier computer's ExpressJS server. I did it this way as NWJS has a kiosk functionality that I can use so that the station computers will strictly act as stations for the employees to use.


IMPOSS 3.0

You might have wondered, if v2 was done, why the heck is there a v3? Let me talk to you about one of the inconveniences that I have with v2 that I was itching to fix for so long. v2 had a very bad issue with maintainability and new feature additions. The codebase was super messy, I was not using a frontend framework so the entire codebase was basically a big pile of JavaScript code being plastered all over. Minor issues related to stability and centavos inconsistencies with the data being pushed to the database is a big factor also as it's a business dealing with money. You can't have those issues lying around unfixed as it could slowly compound. However, the last push that made me do v3 is that, the client was opening a second branch, and she wanted a new feature, which is interoperability between the two branches. That's where I decided to finally do the refactor to v3 instead of trying my best to hammer the interoperability between two branches feature in v2.

IMPOSS 3.0 Login Window Preview

Version 3 was such a feat compared to v2 as there was so much improvement that happened. All the issues from v2 was fixed as I was now using a library to handle money transactions instead of doing math all by myself (curse you floating point arithmetic). I would also like to point out that I am now finally using a frontend framework for this refactor. SvelteKit.

This frontend framework was amazing to work with. It fits so much nicely to how I like doing things. Everything is contained in some kind of islands, where logic, data manipulation, and UI/UX just sits there independent of each other. This is also the framework that introduced me to JSDOC, and the importance of type safety. Before this, I was very much a typescript hater myself, and even now, even with type safety in mind, I still hate the build process aspect of it, which is the reason why I fell in love with JSDOC as you can still have type safety in mind, without the hassle of including an extra build process of transpiling that code back to JavaScript before running it.


Implementation of v3


It was such a godsend that I discovered ZeroTier. I have no idea how I found it in the first place, but I just did. It's what made all of this branch interoperability work without having to rent and spin up an entire server to have a middle man throwing data in between the two servers.

I also decided to split up the frontend and backend of the application as to have some more flexibility with hosting the frontend and/or backend in the future, along with wanting to protect my backend source code by compiling it to an executable using the pkg library from vercel. This way, when I want to upgrade the station and cashier computers, all I needed to do was to send this executable to them and replace the one they currently have. (The application can automatically download updates, so it basically does this semi-automatically now. The user only needs to click on an update button or restart the application to install updates.)

I ported away from MySQL and instead went to a simpler database technology, SQLite. I was fascinated that this database technology is battle-tested, both metaphorically and literally as it's durable enough to be used allegedly in a military setting. I'm not saying that it's a perfect database, but for my use case, it works just fine. Besides, if I ever want to use a different database, my backend is using Prisma ORM, so I can simply write up a script to migrate a database from my old one to a new one, do a database migrate of the schema, then run the migration script.

And that's it, v3 is done, but it will still receive some bug fixes and updates from time to time, especially if the client has some new feature requests in mind that she wants implemented. And besides, I still have some work to do. As you can see in the v3 flowchart, I have yet to implement embedded replicas on my backend. It would be a nice to have so that one branch can edit the database of another branch without that branch requiring their server or cashier computer to be spun up.

I would like to shout out one of the libraries that I used for this project that is such a workhorse for all three versions of this application. Olifolkerd's Tabulator. It has basically all the features that I need, especially the super flexible AJAX data loading and its virtual tables for performance. I feel like it would have been way harder developing this app without this amazing library to lean on to.

And that concludes my journey with this application so far. I will update this accordingly when new major stuff related to this app comes. For now, feel free to read my other portfolio and blog articles.


If you are interested and want to see a demo of this app for your business, feel free to contact me at [email protected]. Keep in mind that although this app is mainly being used in a pharmacy setting, this is not constrained for a pharmacy business use only.

-