137 lines
4.2 KiB
Go
137 lines
4.2 KiB
Go
//go:build ignore
|
|
|
|
// Read-only verification for the base-handover work. Reads information_schema
|
|
// and pg_constraint only — no writes, no DDL, no migrations.
|
|
//
|
|
// go run scratch/check_handover_schema.go
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
|
|
"doormile/config"
|
|
"doormile/db"
|
|
|
|
"github.com/joho/godotenv"
|
|
)
|
|
|
|
func main() {
|
|
_ = godotenv.Load()
|
|
cfg := config.Load()
|
|
db.Connect(cfg)
|
|
if db.DB == nil {
|
|
log.Fatal("no DB connection")
|
|
}
|
|
|
|
fmt.Println("=== 1. New columns (expected ABSENT until AutoMigrate runs) ===")
|
|
type col struct {
|
|
Table string
|
|
Name string
|
|
}
|
|
for _, want := range []col{
|
|
{"pickupbookings", "pickupsourcetype"},
|
|
{"pickupbookings", "pickuphubid"},
|
|
{"consignments", "inwardedat"},
|
|
} {
|
|
var n int64
|
|
db.DB.Raw(`SELECT count(*) FROM information_schema.columns
|
|
WHERE table_name = ? AND column_name = ?`, want.Table, want.Name).Scan(&n)
|
|
fmt.Printf(" %-16s %-18s present=%v\n", want.Table, want.Name, n > 0)
|
|
}
|
|
|
|
fmt.Println("\n=== 2. CHECK constraints on the tables we write ===")
|
|
type chk struct {
|
|
Conname string
|
|
Def string
|
|
}
|
|
var checks []chk
|
|
db.DB.Raw(`SELECT c.conname, pg_get_constraintdef(c.oid) AS def
|
|
FROM pg_constraint c JOIN pg_class t ON t.oid = c.conrelid
|
|
WHERE c.contype = 'c'
|
|
AND t.relname IN ('consignments','consignmentexceptions','consignmenthistory',
|
|
'pickupbookings','bookingassignments','milerprofiles')
|
|
ORDER BY t.relname, c.conname`).Scan(&checks)
|
|
for _, c := range checks {
|
|
fmt.Printf(" %s\n %s\n", c.Conname, c.Def)
|
|
}
|
|
|
|
fmt.Println("\n=== 3. Foreign keys on the user/id columns we write ===")
|
|
type fk struct {
|
|
Table string
|
|
Conname string
|
|
Def string
|
|
}
|
|
var fks []fk
|
|
db.DB.Raw(`SELECT t.relname AS table, c.conname, pg_get_constraintdef(c.oid) AS def
|
|
FROM pg_constraint c JOIN pg_class t ON t.oid = c.conrelid
|
|
WHERE c.contype = 'f'
|
|
AND t.relname IN ('consignmentexceptions','consignmenthistory','consignments',
|
|
'tripsheets','bookingassignments','pickupbookings')
|
|
ORDER BY t.relname, c.conname`).Scan(&fks)
|
|
if len(fks) == 0 {
|
|
fmt.Println(" (none)")
|
|
}
|
|
for _, f := range fks {
|
|
fmt.Printf(" %-24s %s\n", f.Table, f.Def)
|
|
}
|
|
|
|
fmt.Println("\n=== 4. NOT NULL columns on the tables we insert into ===")
|
|
type nn struct {
|
|
Table string
|
|
Column string
|
|
Def *string
|
|
}
|
|
var nns []nn
|
|
db.DB.Raw(`SELECT table_name AS table, column_name AS column, column_default AS def
|
|
FROM information_schema.columns
|
|
WHERE table_name IN ('consignmentexceptions','consignmenthistory')
|
|
AND is_nullable = 'NO'
|
|
ORDER BY table_name, ordinal_position`).Scan(&nns)
|
|
for _, c := range nns {
|
|
d := "(no default)"
|
|
if c.Def != nil {
|
|
d = *c.Def
|
|
}
|
|
fmt.Printf(" %-24s %-20s %s\n", c.Table, c.Column, d)
|
|
}
|
|
|
|
fmt.Println("\n=== 5. Hub master data completeness (request 29) ===")
|
|
type hubRow struct {
|
|
Total int64
|
|
NoAddress int64
|
|
NoPincode int64
|
|
NoCoords int64
|
|
ActiveTotal int64
|
|
}
|
|
var h hubRow
|
|
db.DB.Raw(`SELECT count(*) AS total,
|
|
count(*) FILTER (WHERE address IS NULL OR address = '') AS no_address,
|
|
count(*) FILTER (WHERE pincode IS NULL OR pincode = '') AS no_pincode,
|
|
count(*) FILTER (WHERE latitude IS NULL OR latitude = 0 OR longitude IS NULL OR longitude = 0) AS no_coords,
|
|
count(*) FILTER (WHERE status = 'Active') AS active_total
|
|
FROM hubs WHERE deletedat IS NULL`).Scan(&h)
|
|
fmt.Printf(" hubs=%d active=%d missing_address=%d missing_pincode=%d missing_coords=%d\n",
|
|
h.Total, h.ActiveTotal, h.NoAddress, h.NoPincode, h.NoCoords)
|
|
|
|
fmt.Println("\n=== 6. Consignment status distribution (what is live now) ===")
|
|
type sc struct {
|
|
Status string
|
|
N int64
|
|
}
|
|
var scs []sc
|
|
db.DB.Raw(`SELECT status, count(*) AS n FROM consignments
|
|
WHERE deletedat IS NULL GROUP BY status ORDER BY n DESC`).Scan(&scs)
|
|
for _, s := range scs {
|
|
fmt.Printf(" %-22s %d\n", s.Status, s.N)
|
|
}
|
|
|
|
fmt.Println("\n=== 7. Open assignments on already-converted bookings (the off-duty bug) ===")
|
|
var stuck int64
|
|
db.DB.Raw(`SELECT count(*) FROM bookingassignments a
|
|
JOIN pickupbookings b ON b.bookingid = a.bookingid
|
|
WHERE a.assignmentstatus IN ('Assigned','Accepted')
|
|
AND b.status = 'Converted_To_Consignment'`).Scan(&stuck)
|
|
fmt.Printf(" assignments still open on a converted booking: %d\n", stuck)
|
|
}
|