feat: integrate Grafana dashboards into BOC DashboardPage
- Add Infrastructure Health section with CPU/Memory/Disk panels - Add Service Status section with PM2/Docker panels - Create GrafanaPanel component for iframe embedding - Build passes successfully
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"boc/repository"
|
||||
)
|
||||
|
||||
// HRService handles business logic for HR operations
|
||||
type HRService struct {
|
||||
repo *repository.HRRepository
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func NewHRService(db *sql.DB) *HRService {
|
||||
return &HRService{
|
||||
repo: repository.NewHRRepository(db),
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
// ListEmployees returns all employees
|
||||
func (s *HRService) ListEmployees(ctx context.Context) ([]repository.Employee, error) {
|
||||
return s.repo.ListEmployees(ctx)
|
||||
}
|
||||
|
||||
// GetEmployee returns a single employee by ID
|
||||
func (s *HRService) GetEmployee(ctx context.Context, id string) (*repository.Employee, error) {
|
||||
return s.repo.GetEmployee(ctx, id)
|
||||
}
|
||||
|
||||
// CreateEmployee creates a new employee with validation
|
||||
func (s *HRService) CreateEmployee(ctx context.Context, e *repository.Employee) error {
|
||||
if e.Name == "" {
|
||||
return fmt.Errorf("employee name is required")
|
||||
}
|
||||
if e.Email == "" {
|
||||
return fmt.Errorf("employee email is required")
|
||||
}
|
||||
if e.Status == "" {
|
||||
e.Status = "active"
|
||||
}
|
||||
return s.repo.CreateEmployee(ctx, e)
|
||||
}
|
||||
|
||||
// UpdateEmployee updates an existing employee
|
||||
func (s *HRService) UpdateEmployee(ctx context.Context, id string, e *repository.Employee) error {
|
||||
if e.Name == "" {
|
||||
return fmt.Errorf("employee name is required")
|
||||
}
|
||||
return s.repo.UpdateEmployee(ctx, id, e)
|
||||
}
|
||||
|
||||
// ListLeaves returns all leave requests
|
||||
func (s *HRService) ListLeaves(ctx context.Context) ([]repository.Leave, error) {
|
||||
return s.repo.ListLeaves(ctx)
|
||||
}
|
||||
|
||||
// CreateLeave creates a new leave request with validation
|
||||
func (s *HRService) CreateLeave(ctx context.Context, l *repository.Leave) error {
|
||||
if l.EmployeeID == "" {
|
||||
return fmt.Errorf("employee ID is required")
|
||||
}
|
||||
if l.Type == "" {
|
||||
return fmt.Errorf("leave type is required")
|
||||
}
|
||||
if l.Status == "" {
|
||||
l.Status = "pending"
|
||||
}
|
||||
return s.repo.CreateLeave(ctx, l)
|
||||
}
|
||||
|
||||
// ListTimesheets returns all timesheet entries
|
||||
func (s *HRService) ListTimesheets(ctx context.Context) ([]repository.Timesheet, error) {
|
||||
return s.repo.ListTimesheets(ctx)
|
||||
}
|
||||
|
||||
// CreateTimesheet creates a new timesheet entry with validation
|
||||
func (s *HRService) CreateTimesheet(ctx context.Context, t *repository.Timesheet) error {
|
||||
if t.EmployeeID == "" {
|
||||
return fmt.Errorf("employee ID is required")
|
||||
}
|
||||
if t.Hours <= 0 {
|
||||
return fmt.Errorf("hours must be positive")
|
||||
}
|
||||
if t.Status == "" {
|
||||
t.Status = "pending"
|
||||
}
|
||||
return s.repo.CreateTimesheet(ctx, t)
|
||||
}
|
||||
Reference in New Issue
Block a user