The key item here is the last line. Yes, I have many examples in my old ERP system where lots of stuff needs to happen to multiple things as a part of a business transaction. I'm not entirely sure that it all needs to be a part of an actual transaction, see below, but for the moment lets assume that it does.
You don't say where the info for all of this comes from, but let's assume that there is some set of temp-tables, perhaps a PDS, that you fill and validate either based on user input or interaction with a data stream or whatever. Or, perhaps this is a previously persisted order that came from the database, was modified, and now needs to be put back. The logic to do that is going to be walking through, either using something like save-changes or explicitly creating buffers and doing buffer copy. OK, where in there do you need to empty any temp-tables? After you are done, when the transaction is over, then you may want to empty the TT to get a fresh start, but why during the transaction itself? I don't see anything in that logic which implies the need to empty a TT.
Yes, the sales invoices have earlier entered the database via the business logic called via whatever source (user entry, import, web service, sales order processing). Processing then, among the other things listed above, transforms the sales invoice to the sales journal entry temp-tables to be passed to the sales journal entry business logic.
Sales invoice processing determines transaction control (one grouped sales invoice is a transaction), but has no control over what happens in sales journal entry business logic. Sales journal entry business logic has one responsibility and that is to validate a sales journal entry before writing them to the database. Sales journal entry business logic has various backup temp-tables to aid in calculation / provide multi-user checks / do what ever else. These temp-tables are only known to sales journal entry business logic and are cleaned out after every sales journal entry, therefore they must be emptied in sales journal entry. Sales journal entry does not care who is calling it or whether it is in a transaction.
As for the transaction scope, there is a tendency for ABLers to equate business transaction with DB transaction. After all, this seems to be a natural way to insure atomic purity. The problem with this assumption in modern systems is that the parts of the business transaction may be on different servers. E.g., the basic transaction could be happening in an OP service, but updating the item information could be in an Inventory service and the AR parts might be in an AR service. There are technologies for distributed transactions, but that is just as bad an idea as stateful AppServers and locked agents. One may avoid inconsistencies in the data, but at the expense of driving the system to its knees. This leads to an architecture where there are async messages, exception messages, and rollback logic instead of relying on DB transactions. Point being, with reliable messaging, it is going to work as planned nearly all of the time so the exception handling will be very rarely invoked. It is not quite so tidy as wrapping it all in a DB transaction, but the advantages can be substantial.
Reliable messaging and functional rollback do allow the business transaction to be easily chopped up into smaller pieces,
but this does involve work. If your business transaction is on one server, this work which may get the software ready for something in the future will only introduce bugs, only has the benefit of getting you ready for something which may be useful in the future allowing for a smaller lock table.
I am reminded of a customer some years back who used to get a check once a month that would pay off as many as 7000 invoices (many branch stores). Because each invoice touched multiple tables, this meant a single transaction that touched something near 30,000 records ... all locked, of course ... which blew my idea of reasonable levels of -L. I handled this at the time by just bumping -L for that site, but in retrospect I realize that one could have restructured it into a restartable process and kept the transaction to a single invoice. In your logic above, a few flags would tell you whether or not you had completed a given step and one could then make each step its own DB transaction, but the process would be restartable if aborted in the middle.
Adding flags complicates the process. If I only the sales invoice (with lines) and the sales journal entry (with lines) were involved it would already be a mess:
- add flag to sales invoice indicating 'processed'
- add flag to sales invoice lines indicating 'processed'
- add flag to sales journal header indicating 'incomplete, being processed'
- add flag to sales journal lines indicating 'incomplete, being processed'
Sales invoice business needs a restart processing function / processing needs to be aware that when handling a partially processed sales invoice it needs to continue with the existing sales journal entry.
Sales journal business logic needs to block users from processing or doing anything else with this sales journal entry.
Reports need to exclude these 'incomplete' journal entries.
I say let the database do its job so that we do not have to compensate with extra lines of code.