Files
backend_fiesta/scratch/dbinspect/cleanup.go
Suriya 64a219e7da Stop tracking .env
It has been in the repository since the initial commit carrying the live
database host, user and password. Removing it from the index stops that
getting worse; the credentials are still in history and should be
rotated, which needs coordinating with everything that reads them.

Deployments should pass configuration as container environment rather
than shipping a file — a file on disk is one `git add -f` away from
being committed again.

Also closes the last untested path: a shopper registration published
over the broker rather than posted over HTTP. All three MQTT topics —
order, customer and health — have now been fired against the live
Mosquitto instance and acknowledged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 17:56:09 +05:30

123 lines
4.3 KiB
Go

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.
// Every mobile the probes registered, so a cleanup run leaves nothing behind.
var probeMobiles = []string{"9840012345", "9840099999", "9840077777"}
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.
for _, mobile := range probeMobiles {
// 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 IN
(SELECT customerid FROM customers WHERE contactno = ?)`,
mobile).Scan(&referenced)
if referenced > 0 {
fmt.Printf(" customer %s left in place — %d order(s) reference it\n",
mobile, referenced)
continue
}
res := db.Exec(`DELETE FROM customers WHERE contactno = ?`, mobile)
if res.RowsAffected > 0 {
fmt.Printf(" removed probe customer %s\n", mobile)
}
}
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)
}
}