As the challenge requires the logic of the BillingService class was fully implemented. This now allows the caller of this service to perform charges of unpaid (Pending) invoices of Antaeus customers.
- charges are performed only on the first day of the month.
- upon each charge, an external service is called to bill the customer and the Antaeus customer invoice status is updated to ‘Paid’.
- a result object is returned with the summary of the processed invoices (failed, processed, rejected).
- failed invoices (exceptions) are recorded as part of the result, however additional logging/handling would be more suitable in a real-world application.
A test class of the Billing Service was added. The class includes basic unit tests, with some extended tests which would be able to run with a database access that is beyond what is currently provided in by the MockK library.
The following describes some missing capabilites/features which is worth considering, mainly for a real-case production system.
As the Billing Service performs two separate operations; one of charging the customer account through an external service and the other updating the Antaeus database, it is crucial these two actions would be isolated as one transaction. This is crucial to make sure that no customer is being charged without the Antaeus invoice to be marked as 'Paid', and there need to be locks to ensure that there are no errors due to simultaneous billings.
Payment charges are a very sensitive matter for both the SaaS company and the customer. Because of this, in a real-life service, I would invest more resouces into monitoring those charges in the following ways:
- Maintain a database which stores the charges’ history.
- Notify and handle immediately (possibly manually) any invoices which were charged by the External service but failed to be updated to ‘Paid’ due to an Anateuas internal error.
- Create a process to handle invoices which are pending for an unreasonable amount of time (could be due to recurring internal failures, insufficient funds etc.).
As the invoice charges currently run synchronously (fetched and processed one-by-one), this could be an expensive and inefficient task as Antaeus’ number of invoices grows larger. As a future improvement, a queue, for instance, could be used to increase the performance when several different concurrent threads would pull the pending messages from the queue.
Local holidays might be taken into consideration and shift the charge from the 1st day of the month to the next business day in case there is a holiday on the 1st. External APIs would may provide the needed market holiday data.
Love getting feedback and making my applications even better, thank you!