1. Create a reservation liability (invoice) [debit the reservation cost]
2. Create a tax liability (tax account)
The preceding may happen asynchronously ahead of the time. The following are generally wrapped in a single database transaction:
3. Credit a user's account for value of (total) payment
(3a. Depending on how deep your double-entry goes, Debit your Payment Processor)
4. Debit the user's account the reservation amount
5. Credit the reservation account the reservation amount (reservation invoice account should sum to 0 now: no assets, nothing liable)
6. Add reservation event for completed invoice
7. Debit the user's account the tax amount
8. Credit the tax account the tax amount (user's account should sum to 0 now: no assets, nothing liable)
It's been a while since I've worked on a system in this mindset, so apologies if I've got subtle things wrong or debit/credit backwards. That's still too easy to do even when you've done it a million times and even when you aren't rusty years later.
It's far more than "just two rows extra" for proper double entry with the right number of "accounts" and a lot more things form "accounts" than you think. Some of those accounts should read 0 after a proper transaction. Those become red flags if a transaction failed in the middle, and debugging tools when that happens (is it an extra credit or an extra debit, the account positive or negative/owed something or owing something, that can be very useful information to have on the failed database transaction).
It seems like a lot of extra steps, but each step should also reflect your domain model in useful ways: don't create new reservations until a reservation invoice has been filled/paid for. Even in cases where you are doing direct sales to a customer and don't think you need "proper" invoices and that the transactions existing in the first place are good enough, it's still sometimes a useful domain model to have that invoice concept and rather than "fire off" events like "Create Reservation" purely on the sales transaction, have a stronger "state model" with an "Invoice Completion" step. It's an abstraction that sometimes gains you some peace of mind that you don't accidentally make a new reservation from an over-payment or a payment intended for a different purpose.
1. Create a reservation liability (invoice) [debit the reservation cost]
2. Create a tax liability (tax account)
The preceding may happen asynchronously ahead of the time. The following are generally wrapped in a single database transaction:
3. Credit a user's account for value of (total) payment
(3a. Depending on how deep your double-entry goes, Debit your Payment Processor)
4. Debit the user's account the reservation amount
5. Credit the reservation account the reservation amount (reservation invoice account should sum to 0 now: no assets, nothing liable)
6. Add reservation event for completed invoice
7. Debit the user's account the tax amount
8. Credit the tax account the tax amount (user's account should sum to 0 now: no assets, nothing liable)
It's been a while since I've worked on a system in this mindset, so apologies if I've got subtle things wrong or debit/credit backwards. That's still too easy to do even when you've done it a million times and even when you aren't rusty years later.
It's far more than "just two rows extra" for proper double entry with the right number of "accounts" and a lot more things form "accounts" than you think. Some of those accounts should read 0 after a proper transaction. Those become red flags if a transaction failed in the middle, and debugging tools when that happens (is it an extra credit or an extra debit, the account positive or negative/owed something or owing something, that can be very useful information to have on the failed database transaction).
It seems like a lot of extra steps, but each step should also reflect your domain model in useful ways: don't create new reservations until a reservation invoice has been filled/paid for. Even in cases where you are doing direct sales to a customer and don't think you need "proper" invoices and that the transactions existing in the first place are good enough, it's still sometimes a useful domain model to have that invoice concept and rather than "fire off" events like "Create Reservation" purely on the sales transaction, have a stronger "state model" with an "Invoice Completion" step. It's an abstraction that sometimes gains you some peace of mind that you don't accidentally make a new reservation from an over-payment or a payment intended for a different purpose.