Flow
Where my credit screen checks, and where it does not
1Row check
A number lower than the old cost, or the row is skipped. Zero still passes.
2Merge by product
Units from every store are summed so one product is one line.
3Supplier email first
If it fails, nothing else is sent.
4Team email
A failure is logged and the send carries on.
5History row
Always marked as success, with no guard against a repeat.
Listing the same product once for every store that had it was what the first version of my new screen would have done; the screen turns a supplier's price drop into a request for money back.
When a supplier cuts a price, the stock already in the stores was bought at the old cost. Old cost minus new price, times the units on hand, is a credit you can ask for. Somebody also has to change the register prices. My screen does both from one button.
From stock list to two emails
It loads the stock list my stock report already uses. Each product gets a box for the new price. A row only counts if you type a number lower than the old cost. Then two emails go out. The supplier gets a credit request with each product and a total. My team gets a short note telling them to update the register. A row is saved to the history.
The repeated product
The stock list has one row per store, so a product in three stores shows up three times. But the price box was tied to the product. Type one price and every row for that product filled in, and every one of those rows would go into the email. The supplier would have seen the same item three times. The total was right. The email still looked like I was asking three times.
A second commit that same day merges the rows first.
Rows for the same product have their units added together, so the product appears once.
If you build something like this, decide what one line in the request means, and make the table, the price box and the email all use that same thing.
Two catches with the merge. It keeps the first store's cost, so if stores ever paid different costs for one product, the credit will be wrong. I haven't checked. And the merge is written twice, once for the screen and once for the email, so the two could drift.
When a send fails
The supplier email goes first. If it fails, nothing else goes out. If the team email fails, the code just logs it. The history row then says everything worked, which isn't true. Record each email's result on its own.
Nothing stops the same claim being sent twice from a second tab or a retry, either. Give each claim an id and refuse a repeat.
Numbers from the browser
The server totals the cost and units the browser sends back. It doesn't look them up again, so an old screen means old numbers. A zero price slips through too, and asks for the full cost of the stock. I'd reload the numbers on the server and turn a zero away.