How we split expenses in Fyle
Have you ever received a hotel bill that includes charges for parking, meals, and accommodation? How do you reconcile these expenses for reimbursement? That's where splitting the expense based on categories comes to the rescue.
Hi everyone, I’m Suyash Patil, working as a Member of Technical Staff here at Fyle. In this blog, I’ll be talking about the challenges we faced while developing this feature for admins and approvers.
Context
Historically, at Fyle, we only supported spenders to split expenses based on categories, projects, and cost centers.
This was done through a series of API calls, which included creating the split expenses, deleting the original one, and applying policy rules (if any). Seems okay, right?
Well, the problem here is atomicity. If one of the API calls fails and others succeed, it would create inconsistency in the system. To address this, we should have one API endpoint that performs all the actions in a single transaction. Also, we had to address the requirements of admins and approvers to be able to split expenses inside reports. This is when we decided to migrate the APIs while building the feature for admins and approvers.
Why should we allow admins and approvers to split expense
Before answering this question, I would like you to understand the reconciliation workflow that we have at Fyle
As you can see, there is a lot of back-and-forth in case the admin or approver wants to split expenses. If admin and approvers have this feature to split the expense that is reported, the additional step to send it back to spenders is not needed.
Building new functionality while not breaking existing one
The major challenge in this initiative was to not break the existing feature where spenders can split the expense. Splitting of expenses is one of the critical areas in expense reconciliation flow and breaking this would mean major escalations.
Previously, I worked with the mobile app team which is built in Angular but this was my first time working with AngularJS.
We decided to do this adventure using feature flags, keeping the existing flow intact and building on top of it. Slowly and gradually, I picked up AngularJS architecture, understanding the whole split expense component and related services.
Dealing with edge-cases
At first glance, I thought this problem statement was rather simple and easy to implement (My initial reaction - Okay! We just have to call this API endpoint, and the problem is solved).
As soon as I started working on this initiative, I understood that I underestimated the problem, and edge cases started popping up right from the development phase.
At Fyle, we have various features like restricting projects and categories based on employees, disabling/enabling projects, categories, cost centers, etc. We have to ensure that all the edge cases are covered.
This was my reaction to the whole initiative 🙂.
Development Phase
Before splitting the expense, we have to make sure the splits do not violate organizational policies and all the fields required to code the expense are filled else it would cause problems in reconciliation.
For example, a spender splits a Hotel expense into Food
and Parking
expenses. The food category may have a dependent field Hotel Name
which needs to be filled in. If the expense is split without checking this, it would create an incomplete expense.
To avoid this, we need to first check for policies and mandatory fields, allowing users to add reasons in case of policy violations, and then permit them to split.
The existing flow was actually the opposite of this. We were initially splitting the expense and then checking for policies on individual split expenses. Imagine a user splitting an expense into 20 ways, we have to call 20 APIs to check for policies individually.
All thanks to Kirti who gave us an endpoint to check policies for the splits in a single API.
Understanding UX through a product lens
As engineers, we often see the product from an engineering angle. However, sometimes it is essential to look at the UX with product’s perspective. Let me give you an example to make things clear.
When a user tries to delete an expense, should you show them a warning or not?
From an engineering point of view, this may not sound a bit extra but what if the user accidentally clicks on the delete button?
By throwing a warning, you ensure whether the user wants to delete or it was a misclick. Before starting this initiative, I was a complete novice in the product world and UX before this initiative, and it was a great learning experience for me to learn about UX and product behavior. A huge thanks to Meeha and Mihir for helping me understand how design decisions can greatly impact the overall user experience.
We went through a bunch of edge cases and took decisions on the go, the only idea is that the end user should not be blocked in the flow.
Release of the feature
And now, after countless numbers of code changes, the time has come to unleash the feature. We decided to do a beta release before rolling out the feature. The idea behind doing this is to minimize the risk of bugs and fix them beforehand. With immense courage and confidence, we first released this feature to beta customers. From the outside, I was looking confident but my inner me knew that if something went wrong it would require immediate escalations. For the first few days, we only encountered minor bugs and we decided to roll this out to more customers. Slowly and steadily, we launched this to all the users and we kept close monitoring for an issue that came up. A huge thanks to my manager Aiyush Dhar for helping me in every possible way.
Conclusion
I couldn't express in words how happy and excited I was when the first event was registered. From there to enabling the feature for everyone, it was a complete rollercoaster ride. I would like to thank the entire team for making this happen. Below is a glimpse of the feature usage.