package migrations import ( "doormile/models" "doormile/utils" "gorm.io/gorm" ) func Migrate(db *gorm.DB) error { utils.Info("Starting database auto-migrations for 21 logistics tables...") err := db.AutoMigrate( &models.PartnerInfo{}, &models.Hub{}, &models.Vehicle{}, &models.AppUser{}, &models.MilerProfile{}, &models.AppCustomer{}, &models.AppCustomerLocation{}, &models.Consignment{}, &models.PickupBooking{}, &models.BookingParcel{}, &models.BookingServiceOption{}, &models.BookingPayment{}, &models.BookingAssignment{}, &models.BookingVehicleRequirement{}, &models.Tripsheet{}, &models.TripsheetItem{}, &models.DeliveryProof{}, &models.Pricing{}, &models.ConsignmentHistory{}, &models.ConsignmentException{}, &models.TenantLocation{}, &models.AppLocation{}, &models.Tenant{}, &models.Customer{}, &models.CustomerLocation{}, &models.DoormileClient{}, &models.DoormileAuth{}, &models.CompetitorBranch{}, &models.CarrierPricing{}, &models.DoormilePricing{}, &models.AgentDecision{}, &models.HubStaffAccount{}, &models.HubConversation{}, &models.HubMessage{}, &models.MilerDutyLog{}, &models.MilerBreakLog{}, &models.MilerSupportTicket{}, ) if err != nil { utils.Error("❌ Database migration failed", "error", err) return err } utils.Info("✅ Database migration completed successfully!") if res := db.Exec(`ALTER TABLE agent_decisions ADD COLUMN IF NOT EXISTS context_embedding vector(1536)`); res.Error != nil { utils.Error("❌ Failed to add context_embedding column", "error", res.Error) } else { utils.Info("✅ context_embedding vector column ready") } if res := db.Exec(`CREATE INDEX IF NOT EXISTS idx_agent_decisions_embedding ON agent_decisions USING ivfflat (context_embedding vector_cosine_ops) WITH (lists = 100)`); res.Error != nil { utils.Error("❌ Failed to create ivfflat index on context_embedding", "error", res.Error) } else { utils.Info("✅ ivfflat index on context_embedding ready") } // The tripsheets.status CHECK constraint predates this codebase (not derived // from any gorm tag) and only allowed Draft/Dispatched/Arrived/Cancelled. // Hub batches need an intermediate "Ready" stage before dispatch. db.Exec(`ALTER TABLE tripsheets DROP CONSTRAINT IF EXISTS tripsheets_status_check`) if res := db.Exec(`ALTER TABLE tripsheets ADD CONSTRAINT tripsheets_status_check CHECK (status::text = ANY (ARRAY['Draft','Ready','Dispatched','Arrived','Cancelled']::text[]))`); res.Error != nil { utils.Error("❌ Failed to widen tripsheets_status_check constraint", "error", res.Error) } else { utils.Info("✅ tripsheets_status_check constraint includes Ready") } return nil }