updates on the env and pagination

This commit is contained in:
2026-09-15 17:08:22 +05:30
parent 5c73d769ca
commit bf5a9026fe
5 changed files with 287 additions and 2 deletions

131
scratch/cx_tenant_probe.go Normal file
View 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
}