feat: optimize jobs database querying and immutable indexes
This commit is contained in:
parent
fd9af24e22
commit
9ccb15882e
9 changed files with 612 additions and 99 deletions
|
|
@ -163,10 +163,10 @@ func TestAdminService_GetUser(t *testing.T) {
|
||||||
t.Run("returns user by id", func(t *testing.T) {
|
t.Run("returns user by id", func(t *testing.T) {
|
||||||
userID := "019b5290-9680-7c06-9ee3-c9e0e117251b"
|
userID := "019b5290-9680-7c06-9ee3-c9e0e117251b"
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
mock.ExpectQuery("SELECT id, full_name, email, role, created_at FROM users WHERE id").
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, full_name, email, role, COALESCE(status, 'active'), created_at, phone, bio, avatar_url FROM users WHERE id = $1`)).
|
||||||
WithArgs(userID).
|
WithArgs(userID).
|
||||||
WillReturnRows(sqlmock.NewRows([]string{"id", "name", "email", "role", "created_at"}).
|
WillReturnRows(sqlmock.NewRows([]string{"id", "full_name", "email", "role", "status", "created_at", "phone", "bio", "avatar_url"}).
|
||||||
AddRow(userID, "Test User", "test@example.com", "admin", now))
|
AddRow(userID, "Test User", "test@example.com", "admin", "active", now, "123", "Bio", "url"))
|
||||||
|
|
||||||
user, err := service.GetUser(ctx, userID)
|
user, err := service.GetUser(ctx, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -472,93 +472,92 @@ func TestIsActiveApplicationStatus(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Tests for GetCompanyByUserID
|
// Tests for GetCompanyByUserID
|
||||||
func TestAdminService_GetCompanyByUserID(t *testing.T) {
|
func TestAdminService_GetCompanyByUserID(t *testing.T) {
|
||||||
db, mock, err := sqlmock.New()
|
db, mock, err := sqlmock.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error: %v", err)
|
t.Fatalf("Error: %v", err)
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
svc := NewAdminService(db)
|
svc := NewAdminService(db)
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
// Exact query regex match
|
// Exact query regex match
|
||||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, name, slug, description, logo_url, website, location, active, verified, created_at, updated_at FROM companies WHERE user_id=$1`)).
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, name, slug, description, logo_url, website, location, active, verified, created_at, updated_at FROM companies WHERE user_id=$1`)).
|
||||||
WithArgs("user-1").
|
WithArgs("user-1").
|
||||||
WillReturnRows(sqlmock.NewRows([]string{
|
WillReturnRows(sqlmock.NewRows([]string{
|
||||||
"id", "name", "slug", "description", "logo_url", "website", "location",
|
"id", "name", "slug", "description", "logo_url", "website", "location",
|
||||||
"active", "verified", "created_at", "updated_at",
|
"active", "verified", "created_at", "updated_at",
|
||||||
}).AddRow(
|
}).AddRow(
|
||||||
"comp-1", "Company", "company-slug", nil, nil, nil, nil,
|
"comp-1", "Company", "company-slug", nil, nil, nil, nil,
|
||||||
true, true, now, now,
|
true, true, now, now,
|
||||||
))
|
))
|
||||||
|
|
||||||
// Note: implementation might be using "owner_id" or "user_id". Check failure if any.
|
// Note: implementation might be using "owner_id" or "user_id". Check failure if any.
|
||||||
_, err = svc.GetCompanyByUserID(context.Background(), "user-1")
|
_, err = svc.GetCompanyByUserID(context.Background(), "user-1")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Logf("GetCompanyByUserID error (likely query mismatch): %v", err)
|
t.Logf("GetCompanyByUserID error (likely query mismatch): %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAdminService_DeleteCompanyBasic(t *testing.T) {
|
func TestAdminService_DeleteCompanyBasic(t *testing.T) {
|
||||||
db, mock, err := sqlmock.New()
|
db, mock, err := sqlmock.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error: %v", err)
|
t.Fatalf("Error: %v", err)
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
svc := NewAdminService(db)
|
svc := NewAdminService(db)
|
||||||
|
|
||||||
// Expect GetCompanyByID check first
|
// Expect GetCompanyByID check first
|
||||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, name, slug, description, logo_url, website, location, active, verified, created_at, updated_at FROM companies WHERE id=$1`)).
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, name, slug, description, logo_url, website, location, active, verified, created_at, updated_at FROM companies WHERE id=$1`)).
|
||||||
WithArgs("comp-1").
|
WithArgs("comp-1").
|
||||||
WillReturnRows(sqlmock.NewRows([]string{"id", "company_id", "name"}).AddRow("comp-1", "user-1", "Test Co"))
|
WillReturnRows(sqlmock.NewRows([]string{"id", "company_id", "name"}).AddRow("comp-1", "user-1", "Test Co"))
|
||||||
|
|
||||||
mock.ExpectExec(regexp.QuoteMeta(`DELETE FROM companies WHERE id=$1`)).
|
mock.ExpectExec(regexp.QuoteMeta(`DELETE FROM companies WHERE id=$1`)).
|
||||||
WithArgs("comp-1").
|
WithArgs("comp-1").
|
||||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||||
|
|
||||||
_ = svc.DeleteCompany(context.Background(), "comp-1")
|
_ = svc.DeleteCompany(context.Background(), "comp-1")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAdminService_DeleteEmailTemplateBasic(t *testing.T) {
|
func TestAdminService_DeleteEmailTemplateBasic(t *testing.T) {
|
||||||
db, mock, err := sqlmock.New()
|
db, mock, err := sqlmock.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error: %v", err)
|
t.Fatalf("Error: %v", err)
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
svc := NewAdminService(db)
|
svc := NewAdminService(db)
|
||||||
|
|
||||||
mock.ExpectExec(regexp.QuoteMeta(`DELETE FROM email_templates WHERE slug=$1`)).
|
mock.ExpectExec(regexp.QuoteMeta(`DELETE FROM email_templates WHERE slug=$1`)).
|
||||||
WithArgs("welcome").
|
WithArgs("welcome").
|
||||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||||
|
|
||||||
_ = svc.DeleteEmailTemplate(context.Background(), "welcome")
|
_ = svc.DeleteEmailTemplate(context.Background(), "welcome")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAdminService_GetEmailSettingsBasic(t *testing.T) {
|
func TestAdminService_GetEmailSettingsBasic(t *testing.T) {
|
||||||
db, mock, err := sqlmock.New()
|
db, mock, err := sqlmock.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error: %v", err)
|
t.Fatalf("Error: %v", err)
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
svc := NewAdminService(db)
|
svc := NewAdminService(db)
|
||||||
|
|
||||||
query := `SELECT id, provider, smtp_host, smtp_port, smtp_user, smtp_pass, smtp_secure, sender_name, sender_email, amqp_url, is_active, updated_at
|
query := `SELECT id, provider, smtp_host, smtp_port, smtp_user, smtp_pass, smtp_secure, sender_name, sender_email, amqp_url, is_active, updated_at
|
||||||
FROM email_settings WHERE is_active = true ORDER BY updated_at DESC LIMIT 1`
|
FROM email_settings WHERE is_active = true ORDER BY updated_at DESC LIMIT 1`
|
||||||
|
|
||||||
mock.ExpectQuery(regexp.QuoteMeta(query)).
|
mock.ExpectQuery(regexp.QuoteMeta(query)).
|
||||||
WillReturnRows(sqlmock.NewRows([]string{"id", "provider", "smtp_host", "smtp_port", "smtp_user", "smtp_pass", "smtp_secure", "sender_name", "sender_email", "amqp_url", "is_active", "updated_at"}).
|
WillReturnRows(sqlmock.NewRows([]string{"id", "provider", "smtp_host", "smtp_port", "smtp_user", "smtp_pass", "smtp_secure", "sender_name", "sender_email", "amqp_url", "is_active", "updated_at"}).
|
||||||
AddRow("1", "smtp", "smtp.test.com", 587, "user", "pass", false, "Sender", "sender@test.com", "amqp://", true, time.Now()))
|
AddRow("1", "smtp", "smtp.test.com", 587, "user", "pass", false, "Sender", "sender@test.com", "amqp://", true, time.Now()))
|
||||||
|
|
||||||
settings, err := svc.GetEmailSettings(context.Background())
|
settings, err := svc.GetEmailSettings(context.Background())
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if settings.SMTPHost == nil || *settings.SMTPHost != "smtp.test.com" {
|
if settings.SMTPHost == nil || *settings.SMTPHost != "smtp.test.com" {
|
||||||
t.Errorf("Expected smtp.test.com")
|
t.Errorf("Expected smtp.test.com")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ func TestApplicationService_CreateApplication_Full(t *testing.T) {
|
||||||
mock.ExpectQuery("INSERT INTO applications").
|
mock.ExpectQuery("INSERT INTO applications").
|
||||||
WithArgs(
|
WithArgs(
|
||||||
req.JobID, req.UserID, req.Name, req.Phone, req.LineID, req.WhatsApp, req.Email,
|
req.JobID, req.UserID, req.Name, req.Phone, req.LineID, req.WhatsApp, req.Email,
|
||||||
req.Message, req.ResumeURL, sqlmock.AnyArg(), "pending", sqlmock.AnyArg(), sqlmock.AnyArg(),
|
req.Message, req.ResumeURL, sqlmock.AnyArg(), sqlmock.AnyArg(), "pending", sqlmock.AnyArg(), sqlmock.AnyArg(),
|
||||||
).
|
).
|
||||||
WillReturnRows(sqlmock.NewRows([]string{"id", "created_at", "updated_at"}).
|
WillReturnRows(sqlmock.NewRows([]string{"id", "created_at", "updated_at"}).
|
||||||
AddRow("app-789", time.Now(), time.Now()))
|
AddRow("app-789", time.Now(), time.Now()))
|
||||||
|
|
@ -156,10 +156,10 @@ func TestApplicationService_GetApplications(t *testing.T) {
|
||||||
|
|
||||||
rows := sqlmock.NewRows([]string{
|
rows := sqlmock.NewRows([]string{
|
||||||
"id", "job_id", "user_id", "name", "phone", "line_id", "whatsapp", "email",
|
"id", "job_id", "user_id", "name", "phone", "line_id", "whatsapp", "email",
|
||||||
"message", "resume_url", "status", "created_at", "updated_at",
|
"message", "resume_url", "documents", "answers", "status", "created_at", "updated_at",
|
||||||
}).AddRow(
|
}).AddRow(
|
||||||
"app-1", jobID, "user-1", "John Doe", "123", nil, nil, "john@test.com",
|
"app-1", jobID, "user-1", "John Doe", "123", nil, nil, "john@test.com",
|
||||||
"Hello", "http://resume.pdf", "pending", time.Now(), time.Now(),
|
"Hello", "http://resume.pdf", nil, nil, "pending", time.Now(), time.Now(),
|
||||||
)
|
)
|
||||||
|
|
||||||
mock.ExpectQuery("SELECT id, job_id, user_id, name, phone, line_id, whatsapp, email").
|
mock.ExpectQuery("SELECT id, job_id, user_id, name, phone, line_id, whatsapp, email").
|
||||||
|
|
@ -191,10 +191,10 @@ func TestApplicationService_GetApplicationByID(t *testing.T) {
|
||||||
|
|
||||||
rows := sqlmock.NewRows([]string{
|
rows := sqlmock.NewRows([]string{
|
||||||
"id", "job_id", "user_id", "name", "phone", "line_id", "whatsapp", "email",
|
"id", "job_id", "user_id", "name", "phone", "line_id", "whatsapp", "email",
|
||||||
"message", "resume_url", "documents", "status", "created_at", "updated_at",
|
"message", "resume_url", "documents", "answers", "status", "created_at", "updated_at",
|
||||||
}).AddRow(
|
}).AddRow(
|
||||||
appID, "job-1", "user-1", "Jane Doe", "456", nil, nil, "jane@test.com",
|
appID, "job-1", "user-1", "Jane Doe", "456", nil, nil, "jane@test.com",
|
||||||
"Hi", "http://cv.pdf", nil, "pending", time.Now(), time.Now(),
|
"Hi", "http://cv.pdf", nil, nil, "pending", time.Now(), time.Now(),
|
||||||
)
|
)
|
||||||
|
|
||||||
mock.ExpectQuery("SELECT id, job_id, user_id, name, phone, line_id, whatsapp, email").
|
mock.ExpectQuery("SELECT id, job_id, user_id, name, phone, line_id, whatsapp, email").
|
||||||
|
|
|
||||||
|
|
@ -21,13 +21,18 @@ func TestNewEmailService(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
service := NewEmailService(db, credsSvc)
|
service := NewEmailService(db, credsSvc)
|
||||||
if service == nil {
|
concreteService, ok := service.(*emailServiceImpl)
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("Expected NewEmailService to return *emailServiceImpl")
|
||||||
|
}
|
||||||
|
|
||||||
|
if concreteService == nil {
|
||||||
t.Error("Expected service, got nil")
|
t.Error("Expected service, got nil")
|
||||||
}
|
}
|
||||||
if service.db != db {
|
if concreteService.db != db {
|
||||||
t.Error("Expected db to be set")
|
t.Error("Expected db to be set")
|
||||||
}
|
}
|
||||||
if service.credentialsService != credsSvc {
|
if concreteService.credentialsService != credsSvc {
|
||||||
t.Error("Expected credentialsService to be set")
|
t.Error("Expected credentialsService to be set")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,11 +91,12 @@ func (s *JobService) GetJobs(filter dto.JobFilterQuery) ([]models.JobWithCompany
|
||||||
j.view_count, j.featured_until,
|
j.view_count, j.featured_until,
|
||||||
(SELECT COUNT(*) FROM applications a WHERE a.job_id = j.id) as applications_count
|
(SELECT COUNT(*) FROM applications a WHERE a.job_id = j.id) as applications_count
|
||||||
FROM jobs j
|
FROM jobs j
|
||||||
LEFT JOIN companies c ON j.company_id::text = c.id::text
|
LEFT JOIN companies c ON j.company_id = c.id
|
||||||
LEFT JOIN states r ON j.region_id::text = r.id::text
|
LEFT JOIN states r ON j.region_id = r.id
|
||||||
LEFT JOIN cities ci ON j.city_id::text = ci.id::text
|
LEFT JOIN cities ci ON j.city_id = ci.id
|
||||||
WHERE 1=1`
|
WHERE 1=1`
|
||||||
countQuery := `SELECT COUNT(*) FROM jobs j LEFT JOIN companies c ON j.company_id::text = c.id::text WHERE 1=1`
|
|
||||||
|
countQuery := `SELECT COUNT(*) FROM jobs j WHERE 1=1`
|
||||||
|
|
||||||
var args []interface{}
|
var args []interface{}
|
||||||
argId := 1
|
argId := 1
|
||||||
|
|
@ -105,7 +106,11 @@ func (s *JobService) GetJobs(filter dto.JobFilterQuery) ([]models.JobWithCompany
|
||||||
searchTerm := fmt.Sprintf("%%%s%%", *filter.Search)
|
searchTerm := fmt.Sprintf("%%%s%%", *filter.Search)
|
||||||
clause := fmt.Sprintf(" AND (j.title ILIKE $%d OR j.description ILIKE $%d OR c.name ILIKE $%d)", argId, argId, argId)
|
clause := fmt.Sprintf(" AND (j.title ILIKE $%d OR j.description ILIKE $%d OR c.name ILIKE $%d)", argId, argId, argId)
|
||||||
baseQuery += clause
|
baseQuery += clause
|
||||||
countQuery += clause
|
|
||||||
|
// Se tem busca textual que checa c.name, a query de count *precisa* do JOIN
|
||||||
|
countQueryBase := `SELECT COUNT(*) FROM jobs j LEFT JOIN companies c ON j.company_id = c.id WHERE 1=1` // Usando count interno modificado apenas se tiver c.name
|
||||||
|
countQuery = countQueryBase + clause
|
||||||
|
|
||||||
args = append(args, searchTerm)
|
args = append(args, searchTerm)
|
||||||
argId++
|
argId++
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@ func TestCreateJob(t *testing.T) {
|
||||||
},
|
},
|
||||||
mockRun: func() {
|
mockRun: func() {
|
||||||
mock.ExpectQuery(regexp.QuoteMeta(`INSERT INTO jobs`)).
|
mock.ExpectQuery(regexp.QuoteMeta(`INSERT INTO jobs`)).
|
||||||
WithArgs("1", "user-123", "Go Developer", sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), "published", sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg()).
|
WithArgs("1", "user-123", "Go Developer", sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), "published", sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg()).
|
||||||
WillReturnRows(sqlmock.NewRows([]string{"id", "created_at", "updated_at"}).AddRow("100", time.Now(), time.Now()))
|
WillReturnRows(sqlmock.NewRows([]string{"id", "date_posted", "created_at", "updated_at"}).AddRow("100", time.Now(), time.Now(), time.Now()))
|
||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
|
|
@ -93,17 +93,26 @@ func TestGetJobs(t *testing.T) {
|
||||||
// List query
|
// List query
|
||||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT
|
||||||
j.id, j.company_id, j.title, j.description, j.salary_min, j.salary_max, j.salary_type,
|
j.id, j.company_id, j.title, j.description, j.salary_min, j.salary_max, j.salary_type,
|
||||||
j.employment_type, j.work_mode, j.working_hours, j.location, j.status, j.salary_negotiable, j.is_featured, j.created_at, j.updated_at,
|
j.employment_type, j.work_mode, j.working_hours, j.location, j.status, j.salary_negotiable, j.is_featured, COALESCE(j.date_posted, j.created_at) AS date_posted, j.created_at, j.updated_at,
|
||||||
COALESCE(c.name, '') as company_name, c.logo_url as company_logo_url,
|
CASE
|
||||||
r.name as region_name, ci.name as city_name
|
WHEN c.type = 'CANDIDATE_WORKSPACE' OR c.name LIKE 'Candidate - %' THEN ''
|
||||||
FROM jobs j`)).
|
ELSE COALESCE(c.name, '')
|
||||||
|
END as company_name, c.logo_url as company_logo_url,
|
||||||
|
r.name as region_name, ci.name as city_name,
|
||||||
|
j.view_count, j.featured_until,
|
||||||
|
(SELECT COUNT(*) FROM applications a WHERE a.job_id = j.id) as applications_count
|
||||||
|
FROM jobs j
|
||||||
|
LEFT JOIN companies c ON j.company_id = c.id
|
||||||
|
LEFT JOIN states r ON j.region_id = r.id
|
||||||
|
LEFT JOIN cities ci ON j.city_id = ci.id
|
||||||
|
WHERE 1=1`)).
|
||||||
WillReturnRows(sqlmock.NewRows([]string{
|
WillReturnRows(sqlmock.NewRows([]string{
|
||||||
"id", "company_id", "title", "description", "salary_min", "salary_max", "salary_type",
|
"id", "company_id", "title", "description", "salary_min", "salary_max", "salary_type",
|
||||||
"employment_type", "work_mode", "working_hours", "location", "status", "salary_negotiable", "is_featured", "created_at", "updated_at",
|
"employment_type", "work_mode", "working_hours", "location", "status", "salary_negotiable", "is_featured", "date_posted", "created_at", "updated_at",
|
||||||
"company_name", "company_logo_url", "region_name", "city_name",
|
"company_name", "company_logo_url", "region_name", "city_name", "view_count", "featured_until", "applications_count",
|
||||||
}).AddRow(
|
}).AddRow(
|
||||||
"1", "10", "Dev", "Desc", 100, 200, "m", "ft", "Remote", "40h", "Remote", "open", true, false, time.Now(), time.Now(),
|
"1", "10", "Dev", "Desc", 100, 200, "m", "ft", "Remote", "40h", "Remote", "open", true, false, time.Now(), time.Now(), time.Now(),
|
||||||
"Acme", "url", "Region", "City",
|
"Acme", "url", "Region", "City", 0, nil, 0,
|
||||||
))
|
))
|
||||||
|
|
||||||
// Count query
|
// Count query
|
||||||
|
|
@ -136,15 +145,16 @@ func TestGetJobByID(t *testing.T) {
|
||||||
|
|
||||||
jobID := "100"
|
jobID := "100"
|
||||||
|
|
||||||
// Mocking row for GetJobByID (20 columns)
|
|
||||||
rows := sqlmock.NewRows([]string{
|
rows := sqlmock.NewRows([]string{
|
||||||
"id", "company_id", "title", "description", "salary_min", "salary_max", "salary_type",
|
"id", "company_id", "title", "description", "salary_min", "salary_max", "salary_type",
|
||||||
"employment_type", "working_hours", "location", "region_id", "city_id", "salary_negotiable",
|
"employment_type", "working_hours", "location", "region_id", "city_id",
|
||||||
"requirements", "benefits", "visa_support", "language_level", "status", "created_at", "updated_at",
|
"requirements", "benefits", "visa_support", "language_level", "status", "is_featured", "featured_until", "view_count", "date_posted", "created_at", "updated_at",
|
||||||
|
"salary_negotiable", "currency", "work_mode",
|
||||||
}).AddRow(
|
}).AddRow(
|
||||||
jobID, 1, "Title", "Desc", 100, 200, "m",
|
jobID, 1, "Title", "Desc", 100, 200, "m",
|
||||||
"ft", "40h", "Remote", 0, 0, false,
|
"ft", "40h", "Remote", 0, 0,
|
||||||
nil, nil, false, "N2", "open", time.Now(), time.Now(),
|
nil, nil, false, "N2", "open", false, nil, 0, time.Now(), time.Now(), time.Now(),
|
||||||
|
false, "USD", "remote",
|
||||||
)
|
)
|
||||||
|
|
||||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, company_id`)).
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, company_id`)).
|
||||||
|
|
@ -181,15 +191,16 @@ func TestUpdateJob(t *testing.T) {
|
||||||
WithArgs(newTitle, jobID).
|
WithArgs(newTitle, jobID).
|
||||||
WillReturnRows(sqlmock.NewRows([]string{"id", "updated_at"}).AddRow(jobID, time.Now()))
|
WillReturnRows(sqlmock.NewRows([]string{"id", "updated_at"}).AddRow(jobID, time.Now()))
|
||||||
|
|
||||||
// Expect subsequent SELECT to fetch updated job (20 columns)
|
|
||||||
rows := sqlmock.NewRows([]string{
|
rows := sqlmock.NewRows([]string{
|
||||||
"id", "company_id", "title", "description", "salary_min", "salary_max", "salary_type",
|
"id", "company_id", "title", "description", "salary_min", "salary_max", "salary_type",
|
||||||
"employment_type", "working_hours", "location", "region_id", "city_id", "salary_negotiable",
|
"employment_type", "working_hours", "location", "region_id", "city_id",
|
||||||
"requirements", "benefits", "visa_support", "language_level", "status", "created_at", "updated_at",
|
"requirements", "benefits", "visa_support", "language_level", "status", "is_featured", "featured_until", "view_count", "date_posted", "created_at", "updated_at",
|
||||||
|
"salary_negotiable", "currency", "work_mode",
|
||||||
}).AddRow(
|
}).AddRow(
|
||||||
jobID, 1, newTitle, "Desc", 100, 200, "m",
|
jobID, 1, newTitle, "Desc", 100, 200, "m",
|
||||||
"ft", "40h", "Remote", 0, 0, false,
|
"ft", "40h", "Remote", 0, 0,
|
||||||
nil, nil, false, "N2", "open", time.Now(), time.Now(),
|
nil, nil, false, "N2", "open", false, nil, 0, time.Now(), time.Now(), time.Now(),
|
||||||
|
false, "USD", "remote",
|
||||||
)
|
)
|
||||||
|
|
||||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, company_id`)).
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, company_id`)).
|
||||||
|
|
|
||||||
265
backend/internal/services/test_out.txt
Normal file
265
backend/internal/services/test_out.txt
Normal file
|
|
@ -0,0 +1,265 @@
|
||||||
|
=== RUN TestAdminService_ListCompanies
|
||||||
|
=== RUN TestAdminService_ListCompanies/returns_empty_list_when_no_companies
|
||||||
|
=== RUN TestAdminService_ListCompanies/filters_by_verified_status
|
||||||
|
--- PASS: TestAdminService_ListCompanies (0.00s)
|
||||||
|
--- PASS: TestAdminService_ListCompanies/returns_empty_list_when_no_companies (0.00s)
|
||||||
|
--- PASS: TestAdminService_ListCompanies/filters_by_verified_status (0.00s)
|
||||||
|
=== RUN TestAdminService_ListTags
|
||||||
|
=== RUN TestAdminService_ListTags/returns_empty_list_when_no_tags
|
||||||
|
=== RUN TestAdminService_ListTags/filters_by_category
|
||||||
|
--- PASS: TestAdminService_ListTags (0.00s)
|
||||||
|
--- PASS: TestAdminService_ListTags/returns_empty_list_when_no_tags (0.00s)
|
||||||
|
--- PASS: TestAdminService_ListTags/filters_by_category (0.00s)
|
||||||
|
=== RUN TestAdminService_CreateTag
|
||||||
|
=== RUN TestAdminService_CreateTag/creates_a_new_tag
|
||||||
|
=== RUN TestAdminService_CreateTag/rejects_empty_tag_name
|
||||||
|
--- PASS: TestAdminService_CreateTag (0.00s)
|
||||||
|
--- PASS: TestAdminService_CreateTag/creates_a_new_tag (0.00s)
|
||||||
|
--- PASS: TestAdminService_CreateTag/rejects_empty_tag_name (0.00s)
|
||||||
|
=== RUN TestAdminService_GetUser
|
||||||
|
=== RUN TestAdminService_GetUser/returns_user_by_id
|
||||||
|
admin_service_test.go:173: Unexpected error: Query: could not match actual sql: "SELECT id, full_name, email, role, COALESCE(status, 'active'), created_at, phone, bio, avatar_url FROM users WHERE id = $1" with expected regexp "SELECT id, full_name, email, role, created_at FROM users WHERE id"
|
||||||
|
--- FAIL: TestAdminService_GetUser (0.00s)
|
||||||
|
--- FAIL: TestAdminService_GetUser/returns_user_by_id (0.00s)
|
||||||
|
=== RUN TestAdminService_UpdateCompanyStatus
|
||||||
|
=== RUN TestAdminService_UpdateCompanyStatus/updates_active_status_successfully
|
||||||
|
=== RUN TestAdminService_UpdateCompanyStatus/updates_verified_status_successfully
|
||||||
|
=== RUN TestAdminService_UpdateCompanyStatus/returns_error_when_company_not_found
|
||||||
|
--- PASS: TestAdminService_UpdateCompanyStatus (0.00s)
|
||||||
|
--- PASS: TestAdminService_UpdateCompanyStatus/updates_active_status_successfully (0.00s)
|
||||||
|
--- PASS: TestAdminService_UpdateCompanyStatus/updates_verified_status_successfully (0.00s)
|
||||||
|
--- PASS: TestAdminService_UpdateCompanyStatus/returns_error_when_company_not_found (0.00s)
|
||||||
|
=== RUN TestAdminService_ListUsers
|
||||||
|
=== RUN TestAdminService_ListUsers/returns_users_list
|
||||||
|
--- PASS: TestAdminService_ListUsers (0.00s)
|
||||||
|
--- PASS: TestAdminService_ListUsers/returns_users_list (0.00s)
|
||||||
|
=== RUN TestAdminService_DuplicateJob
|
||||||
|
--- PASS: TestAdminService_DuplicateJob (0.00s)
|
||||||
|
=== RUN TestAdminService_EmailTemplates
|
||||||
|
=== RUN TestAdminService_EmailTemplates/ListEmailTemplates
|
||||||
|
=== RUN TestAdminService_EmailTemplates/CreateEmailTemplate
|
||||||
|
--- PASS: TestAdminService_EmailTemplates (0.00s)
|
||||||
|
--- PASS: TestAdminService_EmailTemplates/ListEmailTemplates (0.00s)
|
||||||
|
--- PASS: TestAdminService_EmailTemplates/CreateEmailTemplate (0.00s)
|
||||||
|
=== RUN TestStringOrNil
|
||||||
|
=== RUN TestStringOrNil/nil_for_invalid
|
||||||
|
=== RUN TestStringOrNil/pointer_for_valid
|
||||||
|
--- PASS: TestStringOrNil (0.00s)
|
||||||
|
--- PASS: TestStringOrNil/nil_for_invalid (0.00s)
|
||||||
|
--- PASS: TestStringOrNil/pointer_for_valid (0.00s)
|
||||||
|
=== RUN TestBuildLocation
|
||||||
|
=== RUN TestBuildLocation/nil_when_both_empty
|
||||||
|
=== RUN TestBuildLocation/city,_state_format
|
||||||
|
=== RUN TestBuildLocation/city_only
|
||||||
|
--- PASS: TestBuildLocation (0.00s)
|
||||||
|
--- PASS: TestBuildLocation/nil_when_both_empty (0.00s)
|
||||||
|
--- PASS: TestBuildLocation/city,_state_format (0.00s)
|
||||||
|
--- PASS: TestBuildLocation/city_only (0.00s)
|
||||||
|
=== RUN TestNormalizeSkills
|
||||||
|
--- PASS: TestNormalizeSkills (0.00s)
|
||||||
|
=== RUN TestIsActiveApplicationStatus
|
||||||
|
--- PASS: TestIsActiveApplicationStatus (0.00s)
|
||||||
|
=== RUN TestAdminService_GetCompanyByUserID
|
||||||
|
admin_service_test.go:501: GetCompanyByUserID error (likely query mismatch): Query: could not match actual sql: "SELECT id, full_name, email, role, COALESCE(status, 'active'), created_at, phone, bio, avatar_url FROM users WHERE id = $1" with expected regexp "SELECT id, name, slug, description, logo_url, website, location, active, verified, created_at, updated_at FROM companies WHERE user_id=\$1"
|
||||||
|
--- PASS: TestAdminService_GetCompanyByUserID (0.00s)
|
||||||
|
=== RUN TestAdminService_DeleteCompanyBasic
|
||||||
|
--- PASS: TestAdminService_DeleteCompanyBasic (0.00s)
|
||||||
|
=== RUN TestAdminService_DeleteEmailTemplateBasic
|
||||||
|
--- PASS: TestAdminService_DeleteEmailTemplateBasic (0.00s)
|
||||||
|
=== RUN TestAdminService_GetEmailSettingsBasic
|
||||||
|
--- PASS: TestAdminService_GetEmailSettingsBasic (0.00s)
|
||||||
|
=== RUN TestAuditService_RecordLogin
|
||||||
|
=== RUN TestAuditService_RecordLogin/records_login_successfully
|
||||||
|
=== RUN TestAuditService_RecordLogin/records_login_without_optional_fields
|
||||||
|
--- PASS: TestAuditService_RecordLogin (0.00s)
|
||||||
|
--- PASS: TestAuditService_RecordLogin/records_login_successfully (0.00s)
|
||||||
|
--- PASS: TestAuditService_RecordLogin/records_login_without_optional_fields (0.00s)
|
||||||
|
=== RUN TestAuditService_ListLogins
|
||||||
|
=== RUN TestAuditService_ListLogins/returns_empty_list_when_no_audits
|
||||||
|
=== RUN TestAuditService_ListLogins/respects_custom_limit
|
||||||
|
--- PASS: TestAuditService_ListLogins (0.00s)
|
||||||
|
--- PASS: TestAuditService_ListLogins/returns_empty_list_when_no_audits (0.00s)
|
||||||
|
--- PASS: TestAuditService_ListLogins/respects_custom_limit (0.00s)
|
||||||
|
=== RUN TestNewChatService
|
||||||
|
--- PASS: TestNewChatService (0.00s)
|
||||||
|
=== RUN TestChatService_SendMessage
|
||||||
|
chat_service_test.go:37: Skipping due to async goroutine requiring real dependencies
|
||||||
|
--- SKIP: TestChatService_SendMessage (0.00s)
|
||||||
|
=== RUN TestChatService_ListMessages
|
||||||
|
=== RUN TestChatService_ListMessages/returns_messages_list
|
||||||
|
=== RUN TestChatService_ListMessages/returns_empty_list_when_no_messages
|
||||||
|
--- PASS: TestChatService_ListMessages (0.00s)
|
||||||
|
--- PASS: TestChatService_ListMessages/returns_messages_list (0.00s)
|
||||||
|
--- PASS: TestChatService_ListMessages/returns_empty_list_when_no_messages (0.00s)
|
||||||
|
=== RUN TestChatService_ListConversations
|
||||||
|
=== RUN TestChatService_ListConversations/lists_conversations_for_candidate
|
||||||
|
=== RUN TestChatService_ListConversations/lists_conversations_for_company
|
||||||
|
=== RUN TestChatService_ListConversations/returns_error_for_invalid_context
|
||||||
|
--- PASS: TestChatService_ListConversations (0.00s)
|
||||||
|
--- PASS: TestChatService_ListConversations/lists_conversations_for_candidate (0.00s)
|
||||||
|
--- PASS: TestChatService_ListConversations/lists_conversations_for_company (0.00s)
|
||||||
|
--- PASS: TestChatService_ListConversations/returns_error_for_invalid_context (0.00s)
|
||||||
|
=== RUN TestMessage_Struct
|
||||||
|
--- PASS: TestMessage_Struct (0.00s)
|
||||||
|
=== RUN TestConversation_Struct
|
||||||
|
--- PASS: TestConversation_Struct (0.00s)
|
||||||
|
=== RUN TestNewEmailService
|
||||||
|
--- PASS: TestNewEmailService (0.00s)
|
||||||
|
=== RUN TestEmailService_SendTemplateEmail_NoAMQPURL
|
||||||
|
=== RUN TestEmailService_SendTemplateEmail_NoAMQPURL/returns_error_when_AMQP_URL_not_configured
|
||||||
|
--- PASS: TestEmailService_SendTemplateEmail_NoAMQPURL (0.00s)
|
||||||
|
--- PASS: TestEmailService_SendTemplateEmail_NoAMQPURL/returns_error_when_AMQP_URL_not_configured (0.00s)
|
||||||
|
=== RUN TestEmailService_SendTemplateEmail_DBError
|
||||||
|
=== RUN TestEmailService_SendTemplateEmail_DBError/handles_db_error_gracefully
|
||||||
|
2026/02/25 06:02:13 [EmailService] Failed to fetch AMQP URL: sql: connection is already closed
|
||||||
|
--- PASS: TestEmailService_SendTemplateEmail_DBError (0.00s)
|
||||||
|
--- PASS: TestEmailService_SendTemplateEmail_DBError/handles_db_error_gracefully (0.00s)
|
||||||
|
=== RUN TestEmailJob_Struct
|
||||||
|
--- PASS: TestEmailJob_Struct (0.00s)
|
||||||
|
=== RUN TestNotificationService_ListNotifications
|
||||||
|
=== RUN TestNotificationService_ListNotifications/returns_empty_list_when_no_notifications
|
||||||
|
--- PASS: TestNotificationService_ListNotifications (0.00s)
|
||||||
|
--- PASS: TestNotificationService_ListNotifications/returns_empty_list_when_no_notifications (0.00s)
|
||||||
|
=== RUN TestNotificationService_CreateNotification
|
||||||
|
=== RUN TestNotificationService_CreateNotification/creates_a_new_notification
|
||||||
|
--- PASS: TestNotificationService_CreateNotification (0.00s)
|
||||||
|
--- PASS: TestNotificationService_CreateNotification/creates_a_new_notification (0.00s)
|
||||||
|
=== RUN TestNotificationService_MarkAsRead
|
||||||
|
=== RUN TestNotificationService_MarkAsRead/marks_notification_as_read
|
||||||
|
--- PASS: TestNotificationService_MarkAsRead (0.00s)
|
||||||
|
--- PASS: TestNotificationService_MarkAsRead/marks_notification_as_read (0.00s)
|
||||||
|
=== RUN TestNotificationService_MarkAllAsRead
|
||||||
|
=== RUN TestNotificationService_MarkAllAsRead/marks_all_notifications_as_read
|
||||||
|
--- PASS: TestNotificationService_MarkAllAsRead (0.00s)
|
||||||
|
--- PASS: TestNotificationService_MarkAllAsRead/marks_all_notifications_as_read (0.00s)
|
||||||
|
=== RUN TestNewNotificationService
|
||||||
|
--- PASS: TestNewNotificationService (0.00s)
|
||||||
|
=== RUN TestNewSettingsService
|
||||||
|
--- PASS: TestNewSettingsService (0.00s)
|
||||||
|
=== RUN TestSettingsService_GetSettings
|
||||||
|
=== RUN TestSettingsService_GetSettings/returns_setting_value
|
||||||
|
=== RUN TestSettingsService_GetSettings/returns_nil_when_not_found
|
||||||
|
=== RUN TestSettingsService_GetSettings/returns_error_on_db_failure
|
||||||
|
--- PASS: TestSettingsService_GetSettings (0.00s)
|
||||||
|
--- PASS: TestSettingsService_GetSettings/returns_setting_value (0.00s)
|
||||||
|
--- PASS: TestSettingsService_GetSettings/returns_nil_when_not_found (0.00s)
|
||||||
|
--- PASS: TestSettingsService_GetSettings/returns_error_on_db_failure (0.00s)
|
||||||
|
=== RUN TestSettingsService_SaveSettings
|
||||||
|
=== RUN TestSettingsService_SaveSettings/saves_setting_successfully
|
||||||
|
=== RUN TestSettingsService_SaveSettings/upserts_existing_setting
|
||||||
|
=== RUN TestSettingsService_SaveSettings/returns_error_on_db_failure
|
||||||
|
=== RUN TestSettingsService_SaveSettings/handles_unmarshalable_value
|
||||||
|
--- PASS: TestSettingsService_SaveSettings (0.00s)
|
||||||
|
--- PASS: TestSettingsService_SaveSettings/saves_setting_successfully (0.00s)
|
||||||
|
--- PASS: TestSettingsService_SaveSettings/upserts_existing_setting (0.00s)
|
||||||
|
--- PASS: TestSettingsService_SaveSettings/returns_error_on_db_failure (0.00s)
|
||||||
|
--- PASS: TestSettingsService_SaveSettings/handles_unmarshalable_value (0.00s)
|
||||||
|
=== RUN TestNewStorageService
|
||||||
|
--- PASS: TestNewStorageService (0.00s)
|
||||||
|
=== RUN TestUploadConfig_Validation
|
||||||
|
--- PASS: TestUploadConfig_Validation (0.00s)
|
||||||
|
=== RUN TestUploadConfig_DefaultRegion
|
||||||
|
--- PASS: TestUploadConfig_DefaultRegion (0.00s)
|
||||||
|
=== RUN TestUploadConfig_IncompleteFields
|
||||||
|
storage_service_test.go:90: Correctly identified incomplete credentials
|
||||||
|
--- PASS: TestUploadConfig_IncompleteFields (0.00s)
|
||||||
|
=== RUN TestAdminService_Extra_Unit
|
||||||
|
--- PASS: TestAdminService_Extra_Unit (0.00s)
|
||||||
|
=== RUN TestAdminService_DuplicateJob
|
||||||
|
--- PASS: TestAdminService_DuplicateJob (0.00s)
|
||||||
|
=== RUN TestAdminService_ListMethods
|
||||||
|
--- PASS: TestAdminService_ListMethods (0.00s)
|
||||||
|
=== RUN TestCreateApplication_Success
|
||||||
|
--- PASS: TestCreateApplication_Success (0.10s)
|
||||||
|
=== RUN TestApplicationService_DeleteApplication
|
||||||
|
--- PASS: TestApplicationService_DeleteApplication (0.00s)
|
||||||
|
=== RUN TestApplicationService_CreateApplication_Full
|
||||||
|
application_service_test.go:136: CreateApplication failed: Query '
|
||||||
|
INSERT INTO applications (
|
||||||
|
job_id, user_id, name, phone, line_id, whatsapp, email,
|
||||||
|
message, resume_url, documents, answers, status, created_at, updated_at
|
||||||
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
|
||||||
|
RETURNING id, created_at, updated_at
|
||||||
|
', arguments do not match: expected 13, but got 14 arguments
|
||||||
|
--- FAIL: TestApplicationService_CreateApplication_Full (0.00s)
|
||||||
|
=== RUN TestApplicationService_GetApplications
|
||||||
|
application_service_test.go:171: GetApplications failed: sql: expected 13 destination arguments in Scan, not 15
|
||||||
|
--- FAIL: TestApplicationService_GetApplications (0.00s)
|
||||||
|
=== RUN TestApplicationService_GetApplicationByID
|
||||||
|
application_service_test.go:206: GetApplicationByID failed: sql: expected 14 destination arguments in Scan, not 15
|
||||||
|
--- FAIL: TestApplicationService_GetApplicationByID (0.00s)
|
||||||
|
=== RUN TestAuxiliaryServices_WithMockDB
|
||||||
|
--- PASS: TestAuxiliaryServices_WithMockDB (0.00s)
|
||||||
|
=== RUN TestLocationService_WithMockRepo
|
||||||
|
--- PASS: TestLocationService_WithMockRepo (0.00s)
|
||||||
|
=== RUN TestNotificationService_SaveFCMToken
|
||||||
|
--- PASS: TestNotificationService_SaveFCMToken (0.00s)
|
||||||
|
=== RUN TestChatService_Constructors
|
||||||
|
--- PASS: TestChatService_Constructors (0.00s)
|
||||||
|
=== RUN TestSaveCredentials
|
||||||
|
--- PASS: TestSaveCredentials (0.00s)
|
||||||
|
=== RUN TestGetDecryptedKey
|
||||||
|
--- PASS: TestGetDecryptedKey (0.48s)
|
||||||
|
=== RUN TestListConfiguredServices
|
||||||
|
--- PASS: TestListConfiguredServices (0.00s)
|
||||||
|
=== RUN TestDeleteCredentials
|
||||||
|
--- PASS: TestDeleteCredentials (0.00s)
|
||||||
|
=== RUN TestEncryptPayload
|
||||||
|
--- PASS: TestEncryptPayload (0.39s)
|
||||||
|
=== RUN TestCreateJob
|
||||||
|
=== RUN TestCreateJob/Success
|
||||||
|
[JOB_SERVICE DEBUG] === CreateJob Started ===
|
||||||
|
[JOB_SERVICE DEBUG] CompanyID=1, CreatedBy=user-123, Title=Go Developer, Status=published
|
||||||
|
[JOB_SERVICE DEBUG] Executing INSERT query...
|
||||||
|
[JOB_SERVICE DEBUG] Job struct: &{ID: CompanyID:1 CreatedBy:user-123 Title:Go Developer Description: SalaryMin:<nil> SalaryMax:<nil> SalaryType:<nil> Currency:<nil> SalaryNegotiable:false EmploymentType:<nil> WorkMode:<nil> WorkingHours:<nil> Location:<nil> RegionID:<nil> CityID:<nil> Requirements:map[] Benefits:map[] Questions:map[] VisaSupport:false LanguageLevel:<nil> Status:published IsFeatured:false ViewCount:0 FeaturedUntil:<nil> DatePosted:2026-02-25 06:02:14.4861294 -0600 CST m=+1.036940001 CreatedAt:2026-02-25 06:02:14.4861294 -0600 CST m=+1.036940001 UpdatedAt:2026-02-25 06:02:14.4861294 -0600 CST m=+1.036940001}
|
||||||
|
[JOB_SERVICE ERROR] INSERT query failed: Query '
|
||||||
|
INSERT INTO jobs (
|
||||||
|
company_id, created_by, title, description, salary_min, salary_max, salary_type, currency,
|
||||||
|
employment_type, work_mode, working_hours, location, region_id, city_id,
|
||||||
|
requirements, benefits, questions, visa_support, language_level, status, date_posted, created_at, updated_at, salary_negotiable
|
||||||
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24)
|
||||||
|
RETURNING id, date_posted, created_at, updated_at
|
||||||
|
', arguments do not match: expected 21, but got 24 arguments
|
||||||
|
job_service_test.go:62: JobService.CreateJob() error = Query '
|
||||||
|
INSERT INTO jobs (
|
||||||
|
company_id, created_by, title, description, salary_min, salary_max, salary_type, currency,
|
||||||
|
employment_type, work_mode, working_hours, location, region_id, city_id,
|
||||||
|
requirements, benefits, questions, visa_support, language_level, status, date_posted, created_at, updated_at, salary_negotiable
|
||||||
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24)
|
||||||
|
RETURNING id, date_posted, created_at, updated_at
|
||||||
|
', arguments do not match: expected 21, but got 24 arguments, wantErr false
|
||||||
|
=== RUN TestCreateJob/DB_Error
|
||||||
|
[JOB_SERVICE DEBUG] === CreateJob Started ===
|
||||||
|
[JOB_SERVICE DEBUG] CompanyID=1, CreatedBy=user-123, Title=Go Developer, Status=
|
||||||
|
[JOB_SERVICE DEBUG] Executing INSERT query...
|
||||||
|
[JOB_SERVICE DEBUG] Job struct: &{ID: CompanyID:1 CreatedBy:user-123 Title:Go Developer Description: SalaryMin:<nil> SalaryMax:<nil> SalaryType:<nil> Currency:<nil> SalaryNegotiable:false EmploymentType:<nil> WorkMode:<nil> WorkingHours:<nil> Location:<nil> RegionID:<nil> CityID:<nil> Requirements:map[] Benefits:map[] Questions:map[] VisaSupport:false LanguageLevel:<nil> Status: IsFeatured:false ViewCount:0 FeaturedUntil:<nil> DatePosted:2026-02-25 06:02:14.4879161 -0600 CST m=+1.038726701 CreatedAt:2026-02-25 06:02:14.4879161 -0600 CST m=+1.038726701 UpdatedAt:2026-02-25 06:02:14.4879161 -0600 CST m=+1.038726701}
|
||||||
|
[JOB_SERVICE ERROR] INSERT query failed: Query '
|
||||||
|
INSERT INTO jobs (
|
||||||
|
company_id, created_by, title, description, salary_min, salary_max, salary_type, currency,
|
||||||
|
employment_type, work_mode, working_hours, location, region_id, city_id,
|
||||||
|
requirements, benefits, questions, visa_support, language_level, status, date_posted, created_at, updated_at, salary_negotiable
|
||||||
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24)
|
||||||
|
RETURNING id, date_posted, created_at, updated_at
|
||||||
|
', arguments do not match: expected 21, but got 24 arguments
|
||||||
|
--- FAIL: TestCreateJob (0.00s)
|
||||||
|
--- FAIL: TestCreateJob/Success (0.00s)
|
||||||
|
--- PASS: TestCreateJob/DB_Error (0.00s)
|
||||||
|
=== RUN TestGetJobs
|
||||||
|
=== RUN TestGetJobs/List_All
|
||||||
|
--- PASS: TestGetJobs (0.00s)
|
||||||
|
--- PASS: TestGetJobs/List_All (0.00s)
|
||||||
|
=== RUN TestGetJobByID
|
||||||
|
job_service_test.go:165: GetJobByID() error = sql: expected 20 destination arguments in Scan, not 26
|
||||||
|
--- FAIL: TestGetJobByID (0.00s)
|
||||||
|
=== RUN TestUpdateJob
|
||||||
|
job_service_test.go:210: UpdateJob() error = sql: expected 20 destination arguments in Scan, not 26
|
||||||
|
--- FAIL: TestUpdateJob (0.00s)
|
||||||
|
=== RUN TestDeleteJob
|
||||||
|
--- PASS: TestDeleteJob (0.00s)
|
||||||
|
=== RUN TestTicketService_CRUD
|
||||||
|
--- PASS: TestTicketService_CRUD (0.00s)
|
||||||
|
=== RUN TestTicketService_Extended
|
||||||
|
--- PASS: TestTicketService_Extended (0.00s)
|
||||||
|
FAIL
|
||||||
|
FAIL github.com/rede5/gohorsejobs/backend/internal/services 1.143s
|
||||||
|
FAIL
|
||||||
57
backend/internal/services/test_out_new.txt
Normal file
57
backend/internal/services/test_out_new.txt
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
--- FAIL: TestAdminService_GetUser (0.00s)
|
||||||
|
--- FAIL: TestAdminService_GetUser/returns_user_by_id (0.00s)
|
||||||
|
admin_service_test.go:173: Unexpected error: Query: could not match actual sql: "SELECT id, full_name, email, role, COALESCE(status, 'active'), created_at, phone, bio, avatar_url FROM users WHERE id = $1" with expected regexp "SELECT id, full_name, email, role, created_at FROM users WHERE id"
|
||||||
|
2026/02/25 06:11:52 [EmailService] Failed to fetch AMQP URL: sql: connection is already closed
|
||||||
|
--- FAIL: TestApplicationService_CreateApplication_Full (0.00s)
|
||||||
|
application_service_test.go:136: CreateApplication failed: Query '
|
||||||
|
INSERT INTO applications (
|
||||||
|
job_id, user_id, name, phone, line_id, whatsapp, email,
|
||||||
|
message, resume_url, documents, answers, status, created_at, updated_at
|
||||||
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
|
||||||
|
RETURNING id, created_at, updated_at
|
||||||
|
', arguments do not match: expected 13, but got 14 arguments
|
||||||
|
--- FAIL: TestApplicationService_GetApplications (0.00s)
|
||||||
|
application_service_test.go:171: GetApplications failed: sql: expected 13 destination arguments in Scan, not 15
|
||||||
|
--- FAIL: TestApplicationService_GetApplicationByID (0.00s)
|
||||||
|
application_service_test.go:206: GetApplicationByID failed: sql: expected 14 destination arguments in Scan, not 15
|
||||||
|
[JOB_SERVICE DEBUG] === CreateJob Started ===
|
||||||
|
[JOB_SERVICE DEBUG] CompanyID=1, CreatedBy=user-123, Title=Go Developer, Status=published
|
||||||
|
[JOB_SERVICE DEBUG] Executing INSERT query...
|
||||||
|
[JOB_SERVICE DEBUG] Job struct: &{ID: CompanyID:1 CreatedBy:user-123 Title:Go Developer Description: SalaryMin:<nil> SalaryMax:<nil> SalaryType:<nil> Currency:<nil> SalaryNegotiable:false EmploymentType:<nil> WorkMode:<nil> WorkingHours:<nil> Location:<nil> RegionID:<nil> CityID:<nil> Requirements:map[] Benefits:map[] Questions:map[] VisaSupport:false LanguageLevel:<nil> Status:published IsFeatured:false ViewCount:0 FeaturedUntil:<nil> DatePosted:2026-02-25 06:11:52.3397837 -0600 CST m=+0.337955101 CreatedAt:2026-02-25 06:11:52.3397837 -0600 CST m=+0.337955101 UpdatedAt:2026-02-25 06:11:52.3397837 -0600 CST m=+0.337955101}
|
||||||
|
[JOB_SERVICE ERROR] INSERT query failed: Query '
|
||||||
|
INSERT INTO jobs (
|
||||||
|
company_id, created_by, title, description, salary_min, salary_max, salary_type, currency,
|
||||||
|
employment_type, work_mode, working_hours, location, region_id, city_id,
|
||||||
|
requirements, benefits, questions, visa_support, language_level, status, date_posted, created_at, updated_at, salary_negotiable
|
||||||
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24)
|
||||||
|
RETURNING id, date_posted, created_at, updated_at
|
||||||
|
', arguments do not match: expected 21, but got 24 arguments
|
||||||
|
[JOB_SERVICE DEBUG] === CreateJob Started ===
|
||||||
|
[JOB_SERVICE DEBUG] CompanyID=1, CreatedBy=user-123, Title=Go Developer, Status=
|
||||||
|
[JOB_SERVICE DEBUG] Executing INSERT query...
|
||||||
|
[JOB_SERVICE DEBUG] Job struct: &{ID: CompanyID:1 CreatedBy:user-123 Title:Go Developer Description: SalaryMin:<nil> SalaryMax:<nil> SalaryType:<nil> Currency:<nil> SalaryNegotiable:false EmploymentType:<nil> WorkMode:<nil> WorkingHours:<nil> Location:<nil> RegionID:<nil> CityID:<nil> Requirements:map[] Benefits:map[] Questions:map[] VisaSupport:false LanguageLevel:<nil> Status: IsFeatured:false ViewCount:0 FeaturedUntil:<nil> DatePosted:2026-02-25 06:11:52.3397837 -0600 CST m=+0.337955101 CreatedAt:2026-02-25 06:11:52.3397837 -0600 CST m=+0.337955101 UpdatedAt:2026-02-25 06:11:52.3397837 -0600 CST m=+0.337955101}
|
||||||
|
[JOB_SERVICE ERROR] INSERT query failed: Query '
|
||||||
|
INSERT INTO jobs (
|
||||||
|
company_id, created_by, title, description, salary_min, salary_max, salary_type, currency,
|
||||||
|
employment_type, work_mode, working_hours, location, region_id, city_id,
|
||||||
|
requirements, benefits, questions, visa_support, language_level, status, date_posted, created_at, updated_at, salary_negotiable
|
||||||
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24)
|
||||||
|
RETURNING id, date_posted, created_at, updated_at
|
||||||
|
', arguments do not match: expected 21, but got 24 arguments
|
||||||
|
--- FAIL: TestCreateJob (0.00s)
|
||||||
|
--- FAIL: TestCreateJob/Success (0.00s)
|
||||||
|
job_service_test.go:62: JobService.CreateJob() error = Query '
|
||||||
|
INSERT INTO jobs (
|
||||||
|
company_id, created_by, title, description, salary_min, salary_max, salary_type, currency,
|
||||||
|
employment_type, work_mode, working_hours, location, region_id, city_id,
|
||||||
|
requirements, benefits, questions, visa_support, language_level, status, date_posted, created_at, updated_at, salary_negotiable
|
||||||
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24)
|
||||||
|
RETURNING id, date_posted, created_at, updated_at
|
||||||
|
', arguments do not match: expected 21, but got 24 arguments, wantErr false
|
||||||
|
--- FAIL: TestGetJobByID (0.00s)
|
||||||
|
job_service_test.go:165: GetJobByID() error = sql: expected 20 destination arguments in Scan, not 26
|
||||||
|
--- FAIL: TestUpdateJob (0.00s)
|
||||||
|
job_service_test.go:210: UpdateJob() error = sql: expected 20 destination arguments in Scan, not 26
|
||||||
|
FAIL
|
||||||
|
FAIL github.com/rede5/gohorsejobs/backend/internal/services 0.441s
|
||||||
|
FAIL
|
||||||
152
backend/migration_error_output.txt
Normal file
152
backend/migration_error_output.txt
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
2026/02/25 06:54:46 Current Working Directory: C:\dev\gohorsejobs\backend
|
||||||
|
2026/02/25 06:54:46 Processing migration: 000_init_uuid_v7.sql (from migrations/000_init_uuid_v7.sql)
|
||||||
|
2026/02/25 06:54:46 Executing migration file migrations/000_init_uuid_v7.sql
|
||||||
|
2026/02/25 06:54:46 Migration 000_init_uuid_v7.sql applied successfully
|
||||||
|
2026/02/25 06:54:46 Processing migration: 001_create_users_table.sql (from migrations/001_create_users_table.sql)
|
||||||
|
2026/02/25 06:54:46 Executing migration file migrations/001_create_users_table.sql
|
||||||
|
2026/02/25 06:54:46 Warning while applying 001_create_users_table.sql: pq: relation "idx_users_identifier" already exists
|
||||||
|
2026/02/25 06:54:46 Processing migration: 002_create_companies_table.sql (from migrations/002_create_companies_table.sql)
|
||||||
|
2026/02/25 06:54:46 Executing migration file migrations/002_create_companies_table.sql
|
||||||
|
2026/02/25 06:54:46 Warning while applying 002_create_companies_table.sql: pq: relation "idx_companies_active" already exists
|
||||||
|
2026/02/25 06:54:46 Processing migration: 003_create_user_companies_table.sql (from migrations/003_create_user_companies_table.sql)
|
||||||
|
2026/02/25 06:54:46 Executing migration file migrations/003_create_user_companies_table.sql
|
||||||
|
2026/02/25 06:54:46 Warning while applying 003_create_user_companies_table.sql: pq: relation "idx_user_companies_user" already exists
|
||||||
|
2026/02/25 06:54:46 Processing migration: 004_create_prefectures_cities_tables.sql (from migrations/004_create_prefectures_cities_tables.sql)
|
||||||
|
2026/02/25 06:54:46 Executing migration file migrations/004_create_prefectures_cities_tables.sql
|
||||||
|
2026/02/25 06:54:46 Migration 004_create_prefectures_cities_tables.sql applied successfully
|
||||||
|
2026/02/25 06:54:46 Processing migration: 005_create_jobs_table.sql (from migrations/005_create_jobs_table.sql)
|
||||||
|
2026/02/25 06:54:46 Executing migration file migrations/005_create_jobs_table.sql
|
||||||
|
2026/02/25 06:54:46 Warning while applying 005_create_jobs_table.sql: pq: relation "idx_jobs_company" already exists
|
||||||
|
2026/02/25 06:54:46 Processing migration: 006_create_applications_table.sql (from migrations/006_create_applications_table.sql)
|
||||||
|
2026/02/25 06:54:46 Executing migration file migrations/006_create_applications_table.sql
|
||||||
|
2026/02/25 06:54:46 Warning while applying 006_create_applications_table.sql: pq: relation "idx_applications_job" already exists
|
||||||
|
2026/02/25 06:54:46 Processing migration: 007_create_favorite_jobs_table.sql (from migrations/007_create_favorite_jobs_table.sql)
|
||||||
|
2026/02/25 06:54:46 Executing migration file migrations/007_create_favorite_jobs_table.sql
|
||||||
|
2026/02/25 06:54:46 Warning while applying 007_create_favorite_jobs_table.sql: pq: relation "idx_favorite_jobs_user" already exists
|
||||||
|
2026/02/25 06:54:46 Processing migration: 008_create_password_resets_table.sql (from migrations/008_create_password_resets_table.sql)
|
||||||
|
2026/02/25 06:54:46 Executing migration file migrations/008_create_password_resets_table.sql
|
||||||
|
2026/02/25 06:54:46 Warning while applying 008_create_password_resets_table.sql: pq: relation "idx_password_resets_token" already exists
|
||||||
|
2026/02/25 06:54:46 Processing migration: 009_unify_schema.sql (from migrations/009_unify_schema.sql)
|
||||||
|
2026/02/25 06:54:46 Executing migration file migrations/009_unify_schema.sql
|
||||||
|
2026/02/25 06:54:46 Migration 009_unify_schema.sql applied successfully
|
||||||
|
2026/02/25 06:54:46 Processing migration: 010_seed_super_admin.sql (from migrations/010_seed_super_admin.sql)
|
||||||
|
2026/02/25 06:54:46 Executing migration file migrations/010_seed_super_admin.sql
|
||||||
|
2026/02/25 06:54:47 Migration 010_seed_super_admin.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 011_add_is_featured_to_jobs.sql (from migrations/011_add_is_featured_to_jobs.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/011_add_is_featured_to_jobs.sql
|
||||||
|
2026/02/25 06:54:47 Migration 011_add_is_featured_to_jobs.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 012_add_work_mode.sql (from migrations/012_add_work_mode.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/012_add_work_mode.sql
|
||||||
|
2026/02/25 06:54:47 Migration 012_add_work_mode.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 013_create_backoffice_tables.sql (from migrations/013_create_backoffice_tables.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/013_create_backoffice_tables.sql
|
||||||
|
2026/02/25 06:54:47 Migration 013_create_backoffice_tables.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 014_update_job_status_constraint.sql (from migrations/014_update_job_status_constraint.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/014_update_job_status_constraint.sql
|
||||||
|
2026/02/25 06:54:47 Migration 014_update_job_status_constraint.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 015_add_candidate_profile_fields.sql (from migrations/015_add_candidate_profile_fields.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/015_add_candidate_profile_fields.sql
|
||||||
|
2026/02/25 06:54:47 Migration 015_add_candidate_profile_fields.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 016_create_notifications_table.sql (from migrations/016_create_notifications_table.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/016_create_notifications_table.sql
|
||||||
|
2026/02/25 06:54:47 Warning while applying 016_create_notifications_table.sql: pq: relation "idx_notifications_user_id" already exists
|
||||||
|
2026/02/25 06:54:47 Processing migration: 017_create_tickets_table.sql (from migrations/017_create_tickets_table.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/017_create_tickets_table.sql
|
||||||
|
2026/02/25 06:54:47 Warning while applying 017_create_tickets_table.sql: pq: relation "tickets" already exists
|
||||||
|
2026/02/25 06:54:47 Processing migration: 018_add_currency_to_jobs.sql (from migrations/018_add_currency_to_jobs.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/018_add_currency_to_jobs.sql
|
||||||
|
2026/02/25 06:54:47 Migration 018_add_currency_to_jobs.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 019_create_job_payments_table.sql (from migrations/019_create_job_payments_table.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/019_create_job_payments_table.sql
|
||||||
|
2026/02/25 06:54:47 Warning while applying 019_create_job_payments_table.sql: pq: relation "idx_job_payments_job_id" already exists
|
||||||
|
2026/02/25 06:54:47 Processing migration: 020_create_fcm_tokens_table.sql (from migrations/020_create_fcm_tokens_table.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/020_create_fcm_tokens_table.sql
|
||||||
|
2026/02/25 06:54:47 Migration 020_create_fcm_tokens_table.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 021_location_hierarchy.sql (from migrations/021_location_hierarchy.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/021_location_hierarchy.sql
|
||||||
|
2026/02/25 06:54:47 Warning while applying 021_location_hierarchy.sql: pq: relation "regions_old" already exists
|
||||||
|
2026/02/25 06:54:47 Processing migration: 022_fix_superadmin_role.sql (from migrations/022_fix_superadmin_role.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/022_fix_superadmin_role.sql
|
||||||
|
2026/02/25 06:54:47 Migration 022_fix_superadmin_role.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 023_ensure_seeded_admins_roles.sql (from migrations/023_ensure_seeded_admins_roles.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/023_ensure_seeded_admins_roles.sql
|
||||||
|
2026/02/25 06:54:47 Migration 023_ensure_seeded_admins_roles.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 024_create_external_services_credentials.sql (from migrations/024_create_external_services_credentials.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/024_create_external_services_credentials.sql
|
||||||
|
2026/02/25 06:54:47 Warning while applying 024_create_external_services_credentials.sql: pq: relation "idx_service_name" already exists
|
||||||
|
2026/02/25 06:54:47 Processing migration: 025_create_chat_tables.sql (from migrations/025_create_chat_tables.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/025_create_chat_tables.sql
|
||||||
|
2026/02/25 06:54:47 Warning while applying 025_create_chat_tables.sql: pq: relation "idx_conversations_candidate" already exists
|
||||||
|
2026/02/25 06:54:47 Processing migration: 026_create_system_settings.sql (from migrations/026_create_system_settings.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/026_create_system_settings.sql
|
||||||
|
2026/02/25 06:54:47 Migration 026_create_system_settings.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 027_create_email_system.sql (from migrations/027_create_email_system.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/027_create_email_system.sql
|
||||||
|
2026/02/25 06:54:47 Migration 027_create_email_system.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 028_add_avatar_url_to_users.sql (from migrations/028_add_avatar_url_to_users.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/028_add_avatar_url_to_users.sql
|
||||||
|
2026/02/25 06:54:47 Migration 028_add_avatar_url_to_users.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 029_expand_employment_types.sql (from migrations/029_expand_employment_types.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/029_expand_employment_types.sql
|
||||||
|
2026/02/25 06:54:47 Migration 029_expand_employment_types.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 030_add_salary_negotiable.sql (from migrations/030_add_salary_negotiable.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/030_add_salary_negotiable.sql
|
||||||
|
2026/02/25 06:54:47 Migration 030_add_salary_negotiable.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 031_add_company_profile_fields.sql (from migrations/031_add_company_profile_fields.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/031_add_company_profile_fields.sql
|
||||||
|
2026/02/25 06:54:47 Migration 031_add_company_profile_fields.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 032_update_superadmin_lol.sql (from migrations/032_update_superadmin_lol.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/032_update_superadmin_lol.sql
|
||||||
|
2026/02/25 06:54:47 Migration 032_update_superadmin_lol.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 033_add_refactor_columns.sql (from migrations/033_add_refactor_columns.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/033_add_refactor_columns.sql
|
||||||
|
2026/02/25 06:54:47 Migration 033_add_refactor_columns.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 034_create_video_interviews.sql (from migrations/034_create_video_interviews.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/034_create_video_interviews.sql
|
||||||
|
2026/02/25 06:54:47 Migration 034_create_video_interviews.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 035_create_job_alerts.sql (from migrations/035_create_job_alerts.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/035_create_job_alerts.sql
|
||||||
|
2026/02/25 06:54:47 Migration 035_create_job_alerts.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 036_create_company_followers.sql (from migrations/036_create_company_followers.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/036_create_company_followers.sql
|
||||||
|
2026/02/25 06:54:47 Migration 036_create_company_followers.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 036_ensure_jobs_work_mode.sql (from migrations/036_ensure_jobs_work_mode.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/036_ensure_jobs_work_mode.sql
|
||||||
|
2026/02/25 06:54:47 Migration 036_ensure_jobs_work_mode.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 037_add_date_posted_to_jobs.sql (from migrations/037_add_date_posted_to_jobs.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/037_add_date_posted_to_jobs.sql
|
||||||
|
2026/02/25 06:54:47 Migration 037_add_date_posted_to_jobs.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 037_add_profile_fields_to_users.sql (from migrations/037_add_profile_fields_to_users.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/037_add_profile_fields_to_users.sql
|
||||||
|
2026/02/25 06:54:47 Migration 037_add_profile_fields_to_users.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 038_create_password_reset_tokens.sql (from migrations/038_create_password_reset_tokens.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/038_create_password_reset_tokens.sql
|
||||||
|
2026/02/25 06:54:47 Warning while applying 038_create_password_reset_tokens.sql: pq: relation "idx_reset_tokens_token" already exists
|
||||||
|
2026/02/25 06:54:47 Processing migration: 039_create_tickets_table_v2.sql (from migrations/039_create_tickets_table_v2.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/039_create_tickets_table_v2.sql
|
||||||
|
2026/02/25 06:54:47 Migration 039_create_tickets_table_v2.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 040_create_activity_logs_table.sql (from migrations/040_create_activity_logs_table.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/040_create_activity_logs_table.sql
|
||||||
|
2026/02/25 06:54:47 Migration 040_create_activity_logs_table.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 041_create_notifications_table_v2.sql (from migrations/041_create_notifications_table_v2.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/041_create_notifications_table_v2.sql
|
||||||
|
2026/02/25 06:54:47 Migration 041_create_notifications_table_v2.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 042_add_view_count_and_job_views.sql (from migrations/042_add_view_count_and_job_views.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/042_add_view_count_and_job_views.sql
|
||||||
|
2026/02/25 06:54:47 Migration 042_add_view_count_and_job_views.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 043_add_company_subscription.sql (from migrations/043_add_company_subscription.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/043_add_company_subscription.sql
|
||||||
|
2026/02/25 06:54:47 Migration 043_add_company_subscription.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 044_add_category_to_tickets.sql (from migrations/044_add_category_to_tickets.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/044_add_category_to_tickets.sql
|
||||||
|
2026/02/25 06:54:47 Migration 044_add_category_to_tickets.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 045_add_answers_to_applications.sql (from migrations/045_add_answers_to_applications.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/045_add_answers_to_applications.sql
|
||||||
|
2026/02/25 06:54:47 Migration 045_add_answers_to_applications.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 046_fix_user_status_varchar.sql (from migrations/046_fix_user_status_varchar.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/046_fix_user_status_varchar.sql
|
||||||
|
2026/02/25 06:54:47 Migration 046_fix_user_status_varchar.sql applied successfully
|
||||||
|
2026/02/25 06:54:47 Processing migration: 047_optimize_job_indexes.sql (from migrations/047_optimize_job_indexes.sql)
|
||||||
|
2026/02/25 06:54:47 Executing migration file migrations/047_optimize_job_indexes.sql
|
||||||
|
2026/02/25 06:54:47 Failed applying migration 047_optimize_job_indexes.sql: pq: function immutable_coalesce_dates(timestamp with time zone, timestamp without time zone) does not exist
|
||||||
|
exit status 1
|
||||||
19
backend/migrations/047_optimize_job_indexes.sql
Normal file
19
backend/migrations/047_optimize_job_indexes.sql
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
-- Migration: 047_optimize_job_indexes
|
||||||
|
-- Description: Creates an immutable wrapper function and a compound index to dramatically optimize the default sorting on the Homepage.
|
||||||
|
-- Removing the heavy Table Scan calculations for `ORDER BY j.is_featured DESC, COALESCE(j.date_posted, j.created_at) DESC`.
|
||||||
|
|
||||||
|
-- 1. Create an immutable function wrapper for COALESCE because PostgreSQL forbids volatile timestamps in indexes
|
||||||
|
CREATE OR REPLACE FUNCTION immutable_coalesce_dates(d1 timestamp with time zone, d2 timestamp without time zone)
|
||||||
|
RETURNS timestamp with time zone AS $$
|
||||||
|
BEGIN
|
||||||
|
RETURN COALESCE(d1, d2 AT TIME ZONE 'UTC');
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql IMMUTABLE;
|
||||||
|
|
||||||
|
-- 2. Create the precise index using the new immutable function
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_jobs_featured_date_posted
|
||||||
|
ON jobs (is_featured DESC, immutable_coalesce_dates(date_posted, created_at) DESC);
|
||||||
|
|
||||||
|
-- 3. Also index jobs creation date explicitly if they search strictly by recents without features
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_jobs_coalesce_date_posted
|
||||||
|
ON jobs (immutable_coalesce_dates(date_posted, created_at) DESC);
|
||||||
Loading…
Reference in a new issue