I will defer to Michael to provide more specifics about his particular implementation / feedback. Based on similar use cases and experience, high level the general setup would be a Pipeline for when a new payment is received that would do something like the following:
Trigger: New Payment received
Query for Invoices with an open Balance.
Loop each Invoice
For each invoice - determine if you have enough funds on the payment to pay off the balance of that invoice. If there is enough, create a transaction between the payment and invoice for the amount outstanding on the invoice as the $ amount of the transaction. Move onto the next invoice and compare the outstanding amount to the payment amount less prior transactions. Repeat the same thing until you can no longer meet the balance of the invoice and you'll end the Pipeline by making a final transaction to an invoice with whatever is left on the payment.
If the final transaction isn't enough to pay the invoice, then you can summarize the total transaction $ that were applied and that brings down the outstanding balance on the invoice.
Your actual transaction table would have 2 relationships, one to invoice and one to payments. Invoices and Payments are both parents to the transaction. The only other field you need is an entry field for Amount to log the actual $ amount.
The above is just based on a generic suggestion of how to handle it. As you have the client aspect and as compared to how you're currently doing you may need to adjust accordingly or incorporate specifics from Michaels suggestions.
------------------------------
Chayce Duncan
------------------------------