I'm already posting this question on StackOverflow, but thought that asking it in different communities might give me different insight. So here's the repost of the question:
Hello, I'm having a financial related service that enable our users to topup their balance in our system, and then disburse the money. They'll be charged for each disbursement. The problem is, I'm having a need to do a series of step that need to be done in several places.
- Transaction : record of the transaction info (amount, beneficiary account, etc)
- Payment : record of the payment info (amount, payment status)
- Journal Entries : record the flow of money for every transaction and payment (for every movement of money in our system, we track which account act as the debit account and which as the credit account, like in accounting)
Flow of the business process:
- Suppose there's a transaction and payment already created, next step is to confirm the transaction
- Change transaction status to confirmed
- Change payment status to confirmed
- Insert new record to journal entries, with debit and credit account specified specifically for this process
- Increment or decrement the balance of the credit and debit account
Those series of step might be done in several places, so I try to find a way to prevent other programmer that try to implement this flow forgetting a step or doing it wrong.
What I do now:
- Create a journal entry helper. Consist of a lot of static function for each of possible business process that involve moving money between accounts. For example in this question, when confirming a payment, it moved money from
user_depositwill be the debit account, and
unearned_revenuewill be the credit account in the newly inserted journal entry. Each of this static function only differ in telling which account will be the credit account and which will be the debit account. Beside that, this helper will also decrement or increment the balance of the credit and debit account. So in this example, it will decrement
user_depositbalance and increment
unearned_revenuebalance. Example function name related to this example:
- Create a payment helper. Different payment type, in different state, will need different journal entry helper. So there are a lot of static function in this helper that change the payment status, and then call the related journal entry helper. Example function name related to this example:
- Create an instance method on the transaction named like
confirmAndwithdraw, which will call
confirmAndWithdrawCashPaymenton payment helper and
withdrawTransactionon journal entry helper, which will call
withdrawPaymenton journal entry helper.
- Whenever a programmer need to do this step, they just call the
confirmAndwithdrawfunction from the transaction object
This'll work of course, but I also know that this is a very bad design. Any suggestion of a design pattern or any solution suitable for this case?
Mainly I'm looking for a way to wrap a series of steps so that I can remove those helper class while also providing a convenient way for other programmers to implement this business process.
Sorry for the long question. If the question is not clear, please do tell me so I can provide more information.