updates on the env and pagination
This commit is contained in:
131
scratch/cx_tenant_probe.go
Normal file
131
scratch/cx_tenant_probe.go
Normal file
@@ -0,0 +1,131 @@
|
||||
//go:build ignore
|
||||
|
||||
// Read-only probe: why a customer-app booking may not reach the console.
|
||||
//
|
||||
// STRICTLY READ-ONLY. SELECTs and COUNTs only — no DDL, no INSERT, no UPDATE,
|
||||
// no DELETE. It answers three questions before anything is changed:
|
||||
//
|
||||
// 1. Do customer-app bookings exist, and what tenantid do they carry?
|
||||
// 2. Which tenants exist, and which are Doormile's own operational ones?
|
||||
// 3. Which console logins are tenant-scoped, and would therefore be unable
|
||||
// to see a booking whose tenantid is NULL?
|
||||
//
|
||||
// go run scratch/cx_tenant_probe.go
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
func main() {
|
||||
_ = godotenv.Load()
|
||||
|
||||
dsn := fmt.Sprintf(
|
||||
"host=%s port=%s user=%s password=%s dbname=%s sslmode=disable",
|
||||
env("DB_HOST", "127.0.0.1"), env("DB_PORT", "5433"),
|
||||
env("DB_USER", "admin"), env("DB_PASSWORD", ""), env("DB_NAME", "logistics"),
|
||||
)
|
||||
|
||||
db, err := sql.Open("postgres", dsn)
|
||||
if err != nil {
|
||||
fmt.Println("open:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer db.Close()
|
||||
if err := db.Ping(); err != nil {
|
||||
fmt.Println("ping:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
section("1. Bookings by source and tenant attribution")
|
||||
rows(db, `
|
||||
SELECT COALESCE(bookingsource,'(null)') AS source,
|
||||
CASE WHEN tenantid IS NULL THEN 'NULL' ELSE 'set' END AS tenant,
|
||||
COUNT(*) AS n,
|
||||
MAX(bookingid) AS newest_id
|
||||
FROM pickupbookings
|
||||
GROUP BY 1,2
|
||||
ORDER BY 1,2`)
|
||||
|
||||
section("2. The 5 newest customer-app bookings")
|
||||
rows(db, `
|
||||
SELECT bookingid, bookingno, COALESCE(tenantid::text,'NULL') AS tenantid,
|
||||
status, COALESCE(customerstatus,'') AS customerstatus, createdat
|
||||
FROM pickupbookings
|
||||
WHERE bookingsource = 'Customer_App'
|
||||
ORDER BY bookingid DESC
|
||||
LIMIT 5`)
|
||||
|
||||
section("3. Tenants")
|
||||
rows(db, `SELECT tenantid, tenantname, status FROM tenants ORDER BY tenantid`)
|
||||
|
||||
section("4. Console logins and their tenant scope (NULL = Doormile staff, sees everything)")
|
||||
rows(db, `
|
||||
SELECT email, role, COALESCE(tenantid::text,'NULL (unscoped)') AS tenant_scope
|
||||
FROM doormile_auth
|
||||
ORDER BY tenantid NULLS FIRST, email`)
|
||||
|
||||
section("5. Total bookings (does the console's page budget still truncate?)")
|
||||
rows(db, `SELECT COUNT(*) AS total_bookings FROM pickupbookings`)
|
||||
}
|
||||
|
||||
func section(title string) { fmt.Printf("\n===== %s =====\n", title) }
|
||||
|
||||
func rows(db *sql.DB, query string) {
|
||||
rs, err := db.Query(query)
|
||||
if err != nil {
|
||||
fmt.Println(" query failed:", err)
|
||||
return
|
||||
}
|
||||
defer rs.Close()
|
||||
|
||||
cols, _ := rs.Columns()
|
||||
fmt.Println(" " + join(cols, " | "))
|
||||
|
||||
for rs.Next() {
|
||||
vals := make([]interface{}, len(cols))
|
||||
ptrs := make([]interface{}, len(cols))
|
||||
for i := range vals {
|
||||
ptrs[i] = &vals[i]
|
||||
}
|
||||
if err := rs.Scan(ptrs...); err != nil {
|
||||
fmt.Println(" scan:", err)
|
||||
return
|
||||
}
|
||||
out := make([]string, len(cols))
|
||||
for i, v := range vals {
|
||||
switch t := v.(type) {
|
||||
case nil:
|
||||
out[i] = "NULL"
|
||||
case []byte:
|
||||
out[i] = string(t)
|
||||
default:
|
||||
out[i] = fmt.Sprint(t)
|
||||
}
|
||||
}
|
||||
fmt.Println(" " + join(out, " | "))
|
||||
}
|
||||
}
|
||||
|
||||
func join(parts []string, sep string) string {
|
||||
s := ""
|
||||
for i, p := range parts {
|
||||
if i > 0 {
|
||||
s += sep
|
||||
}
|
||||
s += p
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func env(k, fallback string) string {
|
||||
if v := os.Getenv(k); v != "" {
|
||||
return v
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
Reference in New Issue
Block a user