package repository import ( "context" "database/sql" "time" ) // Employee represents a company employee type Employee struct { ID string `json:"id"` Name string `json:"name"` Email string `json:"email"` Phone string `json:"phone"` Department string `json:"department"` Position string `json:"position"` StartDate time.Time `json:"start_date"` Status string `json:"status"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // Leave represents a leave request type Leave struct { ID string `json:"id"` EmployeeID string `json:"employee_id"` Type string `json:"type"` StartDate time.Time `json:"start_date"` EndDate time.Time `json:"end_date"` Status string `json:"status"` CreatedAt time.Time `json:"created_at"` } // Timesheet represents a time entry type Timesheet struct { ID string `json:"id"` EmployeeID string `json:"employee_id"` ProjectID *string `json:"project_id"` Date time.Time `json:"date"` Hours float64 `json:"hours"` Description string `json:"description"` Status string `json:"status"` CreatedAt time.Time `json:"created_at"` } // HRRepository handles all HR-related database operations type HRRepository struct { db *sql.DB } func NewHRRepository(db *sql.DB) *HRRepository { return &HRRepository{db: db} } // ListEmployees returns all employees func (r *HRRepository) ListEmployees(ctx context.Context) ([]Employee, error) { rows, err := r.db.QueryContext(ctx, ` SELECT id, name, email, phone, department, position, start_date, status, created_at, updated_at FROM boc_employees ORDER BY name `) if err != nil { return nil, err } defer rows.Close() var employees []Employee for rows.Next() { var e Employee if err := rows.Scan(&e.ID, &e.Name, &e.Email, &e.Phone, &e.Department, &e.Position, &e.StartDate, &e.Status, &e.CreatedAt, &e.UpdatedAt); err != nil { continue } employees = append(employees, e) } return employees, rows.Err() } // GetEmployee returns a single employee by ID func (r *HRRepository) GetEmployee(ctx context.Context, id string) (*Employee, error) { var e Employee err := r.db.QueryRowContext(ctx, ` SELECT id, name, email, phone, department, position, start_date, status, created_at, updated_at FROM boc_employees WHERE id = $1 `, id).Scan(&e.ID, &e.Name, &e.Email, &e.Phone, &e.Department, &e.Position, &e.StartDate, &e.Status, &e.CreatedAt, &e.UpdatedAt) if err != nil { return nil, err } return &e, nil } // CreateEmployee creates a new employee func (r *HRRepository) CreateEmployee(ctx context.Context, e *Employee) error { return r.db.QueryRowContext(ctx, ` INSERT INTO boc_employees (name, email, phone, department, position, start_date, status) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING id, created_at, updated_at `, e.Name, e.Email, e.Phone, e.Department, e.Position, e.StartDate, e.Status).Scan(&e.ID, &e.CreatedAt, &e.UpdatedAt) } // UpdateEmployee updates an existing employee func (r *HRRepository) UpdateEmployee(ctx context.Context, id string, e *Employee) error { _, err := r.db.ExecContext(ctx, ` UPDATE boc_employees SET name = $1, email = $2, phone = $3, department = $4, position = $5, start_date = $6, status = $7, updated_at = NOW() WHERE id = $8 `, e.Name, e.Email, e.Phone, e.Department, e.Position, e.StartDate, e.Status, id) return err } // ListLeaves returns all leave requests func (r *HRRepository) ListLeaves(ctx context.Context) ([]Leave, error) { rows, err := r.db.QueryContext(ctx, ` SELECT id, employee_id, type, start_date, end_date, status, created_at FROM boc_leaves ORDER BY start_date DESC `) if err != nil { return nil, err } defer rows.Close() var leaves []Leave for rows.Next() { var l Leave if err := rows.Scan(&l.ID, &l.EmployeeID, &l.Type, &l.StartDate, &l.EndDate, &l.Status, &l.CreatedAt); err != nil { continue } leaves = append(leaves, l) } return leaves, rows.Err() } // CreateLeave creates a new leave request func (r *HRRepository) CreateLeave(ctx context.Context, l *Leave) error { return r.db.QueryRowContext(ctx, ` INSERT INTO boc_leaves (employee_id, type, start_date, end_date, status) VALUES ($1, $2, $3, $4, $5) RETURNING id, created_at `, l.EmployeeID, l.Type, l.StartDate, l.EndDate, l.Status).Scan(&l.ID, &l.CreatedAt) } // ListTimesheets returns all timesheet entries func (r *HRRepository) ListTimesheets(ctx context.Context) ([]Timesheet, error) { rows, err := r.db.QueryContext(ctx, ` SELECT id, employee_id, project_id, date, hours, description, status, created_at FROM boc_timesheets ORDER BY date DESC LIMIT 100 `) if err != nil { return nil, err } defer rows.Close() var timesheets []Timesheet for rows.Next() { var t Timesheet if err := rows.Scan(&t.ID, &t.EmployeeID, &t.ProjectID, &t.Date, &t.Hours, &t.Description, &t.Status, &t.CreatedAt); err != nil { continue } timesheets = append(timesheets, t) } return timesheets, rows.Err() } // CreateTimesheet creates a new timesheet entry func (r *HRRepository) CreateTimesheet(ctx context.Context, t *Timesheet) error { return r.db.QueryRowContext(ctx, ` INSERT INTO boc_timesheets (employee_id, project_id, date, hours, description, status) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id, created_at `, t.EmployeeID, t.ProjectID, t.Date, t.Hours, t.Description, t.Status).Scan(&t.ID, &t.CreatedAt) }