package main import ( "fmt" "gorm.io/gorm" ) // cleanup removes everything the end-to-end proof wrote to the live database. // // Three things, in an order that leaves nothing half-undone: the stock the test // bills consumed is returned, the bills themselves are deleted, and the price // that was set to make a product sellable goes back to what it was. // // The two test bills are named explicitly rather than deleted by date or by // "everything in pos_orders" — a table that will hold real takings tomorrow is // not one to run an unbounded DELETE against. const probeMobile = "9840012345" var testOrderIDs = []string{ "11111111-2222-4333-8444-555555555555", // the HTTP probe "99999999-8888-4777-8666-555555555555", // the MQTT probe } func cleanup(db *gorm.DB) { var billIDs []int db.Raw(`SELECT posorderid FROM pos_orders WHERE terminalorderid IN ?`, testOrderIDs).Scan(&billIDs) if len(billIDs) == 0 { fmt.Println("no test bills found — nothing to undo") } // Stock first. Deleting the bills before returning what they consumed would // leave the ledger short with nothing left to explain why. var consumed []struct { Productid int Quantity float64 } db.Raw(`SELECT productid, SUM(quantity) AS quantity FROM pos_order_items WHERE posorderid IN ? GROUP BY productid`, billIDs).Scan(&consumed) for _, c := range consumed { qty := int(c.Quantity) if float64(qty) < c.Quantity { qty++ // the ingest rounded up, so the reversal must too } if err := db.Exec(` INSERT INTO productstocks (tenantid, stockdate, locationid, productid, quantity, stocktype, status) VALUES (?, NOW(), ?, ?, ?, 'in', 'Active')`, tenantID, locationID, c.Productid, qty).Error; err != nil { fmt.Println(" return stock:", err) continue } fmt.Printf(" returned %d units of product %d\n", qty, c.Productid) } if len(billIDs) > 0 { db.Exec(`DELETE FROM pos_order_items WHERE posorderid IN ?`, billIDs) db.Exec(`DELETE FROM pos_orders WHERE posorderid IN ?`, billIDs) fmt.Printf(" deleted %d test bill(s)\n", len(billIDs)) } db.Exec(`UPDATE productlocations SET price = 0 WHERE tenantid=? AND locationid=? AND productid=?`, tenantID, locationID, productID) fmt.Printf(" product %d price restored to 0\n", productID) // The shopper the probes created. Removed only when nothing references it — // a customer row attached to a real order is not test data any more. var referenced int db.Raw(`SELECT COUNT(*) FROM orders WHERE customerid = (SELECT MIN(customerid) FROM customers WHERE contactno = ?)`, probeMobile).Scan(&referenced) if referenced > 0 { fmt.Printf(" customer %s left in place — %d order(s) reference it\n", probeMobile, referenced) } else { res := db.Exec(`DELETE FROM customers WHERE contactno = ?`, probeMobile) fmt.Printf(" removed %d probe customer row(s)\n", res.RowsAffected) } var balance float64 db.Raw(`SELECT COALESCE( SUM(CASE WHEN LOWER(stocktype)='in' THEN quantity ELSE 0 END) - SUM(CASE WHEN LOWER(stocktype)='out' THEN quantity ELSE 0 END), 0) FROM productstocks WHERE tenantid=? AND locationid=? AND productid=?`, tenantID, locationID, productID).Scan(&balance) fmt.Printf(" product %d balance back to %.0f\n", productID, balance) } // showCustomer reports whether the registration probe reached the customers // table, and under which id — the question an ack alone cannot answer. func showCustomer(db *gorm.DB, mobile string) { var rows []struct { Customerid int Firstname string Contactno string Applocationid int } db.Raw(`SELECT customerid, COALESCE(firstname,'') AS firstname, COALESCE(contactno,'') AS contactno, COALESCE(applocationid,0) AS applocationid FROM customers WHERE contactno = ?`, mobile).Scan(&rows) if len(rows) == 0 { fmt.Printf(" no customer with contactno %s\n", mobile) return } for _, r := range rows { fmt.Printf(" customerid=%d %q contactno=%s applocid=%d\n", r.Customerid, r.Firstname, r.Contactno, r.Applocationid) } }