292 lines
6.6 KiB
Go
292 lines
6.6 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/rede5/gohorsejobs/backend/internal/models"
|
|
)
|
|
|
|
type AdminService struct {
|
|
DB *sql.DB
|
|
}
|
|
|
|
func NewAdminService(db *sql.DB) *AdminService {
|
|
return &AdminService{DB: db}
|
|
}
|
|
|
|
func (s *AdminService) ListCompanies(ctx context.Context, verified *bool) ([]models.Company, error) {
|
|
baseQuery := `
|
|
SELECT id, name, slug, type, document, address, region_id, city_id, phone, email, website, logo_url, description, active, verified, created_at, updated_at
|
|
FROM companies
|
|
`
|
|
|
|
var args []interface{}
|
|
if verified != nil {
|
|
baseQuery += " WHERE verified = $1"
|
|
args = append(args, *verified)
|
|
}
|
|
baseQuery += " ORDER BY created_at DESC"
|
|
|
|
rows, err := s.DB.QueryContext(ctx, baseQuery, args...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var companies []models.Company
|
|
for rows.Next() {
|
|
var c models.Company
|
|
if err := rows.Scan(
|
|
&c.ID,
|
|
&c.Name,
|
|
&c.Slug,
|
|
&c.Type,
|
|
&c.Document,
|
|
&c.Address,
|
|
&c.RegionID,
|
|
&c.CityID,
|
|
&c.Phone,
|
|
&c.Email,
|
|
&c.Website,
|
|
&c.LogoURL,
|
|
&c.Description,
|
|
&c.Active,
|
|
&c.Verified,
|
|
&c.CreatedAt,
|
|
&c.UpdatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
companies = append(companies, c)
|
|
}
|
|
|
|
return companies, nil
|
|
}
|
|
|
|
func (s *AdminService) UpdateCompanyStatus(ctx context.Context, id int, active *bool, verified *bool) (*models.Company, error) {
|
|
company, err := s.getCompanyByID(ctx, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if active != nil {
|
|
company.Active = *active
|
|
}
|
|
if verified != nil {
|
|
company.Verified = *verified
|
|
}
|
|
|
|
company.UpdatedAt = time.Now()
|
|
query := `
|
|
UPDATE companies
|
|
SET active = $1, verified = $2, updated_at = $3
|
|
WHERE id = $4
|
|
`
|
|
_, err = s.DB.ExecContext(ctx, query, company.Active, company.Verified, company.UpdatedAt, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return company, nil
|
|
}
|
|
|
|
func (s *AdminService) DuplicateJob(ctx context.Context, id int) (*models.Job, error) {
|
|
query := `
|
|
SELECT company_id, created_by, title, description, salary_min, salary_max, salary_type,
|
|
employment_type, work_mode, working_hours, location, region_id, city_id,
|
|
requirements, benefits, visa_support, language_level
|
|
FROM jobs
|
|
WHERE id = $1
|
|
`
|
|
|
|
var job models.Job
|
|
if err := s.DB.QueryRowContext(ctx, query, id).Scan(
|
|
&job.CompanyID,
|
|
&job.CreatedBy,
|
|
&job.Title,
|
|
&job.Description,
|
|
&job.SalaryMin,
|
|
&job.SalaryMax,
|
|
&job.SalaryType,
|
|
&job.EmploymentType,
|
|
&job.WorkMode,
|
|
&job.WorkingHours,
|
|
&job.Location,
|
|
&job.RegionID,
|
|
&job.CityID,
|
|
&job.Requirements,
|
|
&job.Benefits,
|
|
&job.VisaSupport,
|
|
&job.LanguageLevel,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
job.Status = "draft"
|
|
job.IsFeatured = false
|
|
job.CreatedAt = time.Now()
|
|
job.UpdatedAt = time.Now()
|
|
|
|
insertQuery := `
|
|
INSERT INTO jobs (
|
|
company_id, created_by, title, description, salary_min, salary_max, salary_type,
|
|
employment_type, work_mode, working_hours, location, region_id, city_id,
|
|
requirements, benefits, visa_support, language_level, status, is_featured, created_at, updated_at
|
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21)
|
|
RETURNING id
|
|
`
|
|
|
|
if err := s.DB.QueryRowContext(ctx, insertQuery,
|
|
job.CompanyID,
|
|
job.CreatedBy,
|
|
job.Title,
|
|
job.Description,
|
|
job.SalaryMin,
|
|
job.SalaryMax,
|
|
job.SalaryType,
|
|
job.EmploymentType,
|
|
job.WorkMode,
|
|
job.WorkingHours,
|
|
job.Location,
|
|
job.RegionID,
|
|
job.CityID,
|
|
job.Requirements,
|
|
job.Benefits,
|
|
job.VisaSupport,
|
|
job.LanguageLevel,
|
|
job.Status,
|
|
job.IsFeatured,
|
|
job.CreatedAt,
|
|
job.UpdatedAt,
|
|
).Scan(&job.ID); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &job, nil
|
|
}
|
|
|
|
func (s *AdminService) ListTags(ctx context.Context, category *string) ([]models.Tag, error) {
|
|
baseQuery := `SELECT id, name, category, active, created_at, updated_at FROM job_tags`
|
|
var args []interface{}
|
|
if category != nil && *category != "" {
|
|
baseQuery += " WHERE category = $1"
|
|
args = append(args, *category)
|
|
}
|
|
baseQuery += " ORDER BY name ASC"
|
|
|
|
rows, err := s.DB.QueryContext(ctx, baseQuery, args...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var tags []models.Tag
|
|
for rows.Next() {
|
|
var t models.Tag
|
|
if err := rows.Scan(&t.ID, &t.Name, &t.Category, &t.Active, &t.CreatedAt, &t.UpdatedAt); err != nil {
|
|
return nil, err
|
|
}
|
|
tags = append(tags, t)
|
|
}
|
|
|
|
return tags, nil
|
|
}
|
|
|
|
func (s *AdminService) CreateTag(ctx context.Context, name string, category string) (*models.Tag, error) {
|
|
if strings.TrimSpace(name) == "" {
|
|
return nil, fmt.Errorf("tag name is required")
|
|
}
|
|
|
|
now := time.Now()
|
|
tag := models.Tag{
|
|
Name: strings.TrimSpace(name),
|
|
Category: category,
|
|
Active: true,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
|
|
query := `
|
|
INSERT INTO job_tags (name, category, active, created_at, updated_at)
|
|
VALUES ($1, $2, $3, $4, $5)
|
|
RETURNING id
|
|
`
|
|
if err := s.DB.QueryRowContext(ctx, query, tag.Name, tag.Category, tag.Active, tag.CreatedAt, tag.UpdatedAt).Scan(&tag.ID); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &tag, nil
|
|
}
|
|
|
|
func (s *AdminService) UpdateTag(ctx context.Context, id int, name *string, active *bool) (*models.Tag, error) {
|
|
tag, err := s.getTagByID(ctx, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if name != nil {
|
|
trimmed := strings.TrimSpace(*name)
|
|
if trimmed != "" {
|
|
tag.Name = trimmed
|
|
}
|
|
}
|
|
if active != nil {
|
|
tag.Active = *active
|
|
}
|
|
tagUpdatedAt := time.Now()
|
|
query := `
|
|
UPDATE job_tags
|
|
SET name = $1, active = $2, updated_at = $3
|
|
WHERE id = $4
|
|
`
|
|
_, err = s.DB.ExecContext(ctx, query, tag.Name, tag.Active, tagUpdatedAt, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
tag.UpdatedAt = tagUpdatedAt
|
|
return tag, nil
|
|
}
|
|
|
|
func (s *AdminService) getCompanyByID(ctx context.Context, id int) (*models.Company, error) {
|
|
query := `
|
|
SELECT id, name, slug, type, document, address, region_id, city_id, phone, email, website, logo_url, description, active, verified, created_at, updated_at
|
|
FROM companies WHERE id = $1
|
|
`
|
|
var c models.Company
|
|
if err := s.DB.QueryRowContext(ctx, query, id).Scan(
|
|
&c.ID,
|
|
&c.Name,
|
|
&c.Slug,
|
|
&c.Type,
|
|
&c.Document,
|
|
&c.Address,
|
|
&c.RegionID,
|
|
&c.CityID,
|
|
&c.Phone,
|
|
&c.Email,
|
|
&c.Website,
|
|
&c.LogoURL,
|
|
&c.Description,
|
|
&c.Active,
|
|
&c.Verified,
|
|
&c.CreatedAt,
|
|
&c.UpdatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
return &c, nil
|
|
}
|
|
|
|
func (s *AdminService) getTagByID(ctx context.Context, id int) (*models.Tag, error) {
|
|
query := `SELECT id, name, category, active, created_at, updated_at FROM job_tags WHERE id = $1`
|
|
var t models.Tag
|
|
if err := s.DB.QueryRowContext(ctx, query, id).Scan(&t.ID, &t.Name, &t.Category, &t.Active, &t.CreatedAt, &t.UpdatedAt); err != nil {
|
|
return nil, err
|
|
}
|
|
return &t, nil
|
|
}
|