Files
database_render/internal/service/data_service.go
2025-08-05 17:26:59 +08:00

205 lines
5.1 KiB
Go

package service
import (
"fmt"
"log/slog"
"github.com/rogeecn/database_render/internal/config"
"github.com/rogeecn/database_render/internal/database"
"github.com/rogeecn/database_render/internal/model"
"github.com/rogeecn/database_render/internal/repository"
)
// DataService handles business logic for data operations
type DataService struct {
repo *repository.DataRepository
config *config.Config
logger *slog.Logger
}
// NewDataService creates a new data service
func NewDataService(repo *repository.DataRepository, cfg *config.Config) *DataService {
return &DataService{
repo: repo,
config: cfg,
logger: slog.With("component", "service"),
}
}
// GetTables returns all configured tables
func (s *DataService) GetTables() ([]model.TableInfo, error) {
tables, err := s.repo.GetTables()
if err != nil {
s.logger.Error("failed to get tables", "error", err)
return nil, err
}
s.logger.Debug("retrieved tables", "count", len(tables))
return tables, nil
}
// GetTableData returns paginated data for a table
func (s *DataService) GetTableData(tableName string, page, pageSize int, search string, sortField string, sortOrder string) (*model.DataResponse, error) {
// Validate table exists
tableConfig, err := s.repo.GetTableConfig(tableName)
if err != nil {
s.logger.Error("failed to get table config", "table", tableName, "error", err)
return nil, err
}
// Use configured page size if not provided
if pageSize <= 0 {
pageSize = tableConfig.PageSize
}
// Validate page and page size
if page <= 0 {
page = 1
}
if pageSize <= 0 {
pageSize = 10
}
if pageSize > 100 {
pageSize = 100 // Limit maximum page size
}
// Get data from repository
data, total, err := s.repo.GetTableData(tableName, page, pageSize, search, sortField, sortOrder)
if err != nil {
s.logger.Error("failed to get table data",
"table", tableName,
"page", page,
"pageSize", pageSize,
"search", search,
"error", err)
return nil, err
}
// Calculate total pages
totalPages := int((total + int64(pageSize) - 1) / int64(pageSize))
response := &model.DataResponse{
Data: data,
Total: total,
Page: page,
PerPage: pageSize,
Pages: totalPages,
Table: tableName,
Columns: tableConfig.Columns,
Filters: tableConfig.Filters,
}
s.logger.Info("retrieved table data",
"table", tableName,
"page", page,
"pageSize", pageSize,
"total", total,
"pages", totalPages)
return response, nil
}
// GetTableDetail returns a single record detail
func (s *DataService) GetTableDetail(tableName string, id interface{}) (*model.DetailResponse, error) {
// Validate table exists
_, err := s.repo.GetTableConfig(tableName)
if err != nil {
s.logger.Error("failed to get table config", "table", tableName, "error", err)
return nil, err
}
// Get data from repository
data, err := s.repo.GetTableDataByID(tableName, id)
if err != nil {
s.logger.Error("failed to get table detail",
"table", tableName,
"id", id,
"error", err)
return nil, err
}
response := &model.DetailResponse{
Data: data,
}
s.logger.Debug("retrieved table detail",
"table", tableName,
"id", id)
return response, nil
}
// GetTableColumns returns column information for a table
func (s *DataService) GetTableColumns(tableName string) ([]database.ColumnInfo, error) {
// Validate table exists
_, err := s.repo.GetTableConfig(tableName)
if err != nil {
s.logger.Error("failed to get table config", "table", tableName, "error", err)
return nil, err
}
// Get column information from repository
columns, err := s.repo.GetTableColumns(tableName)
if err != nil {
s.logger.Error("failed to get table columns",
"table", tableName,
"error", err)
return nil, err
}
return columns, nil
}
// ValidateConfiguration validates the entire configuration
func (s *DataService) ValidateConfiguration() error {
// Validate tables configuration
if len(s.config.Tables) == 0 {
return fmt.Errorf("no tables configured")
}
// Validate table existence in database
if err := s.repo.ValidateTableConfig(); err != nil {
return err
}
// Validate individual table configurations
for tableName, tableConfig := range s.config.Tables {
if tableConfig.Alias == "" {
return fmt.Errorf("table %s has empty alias", tableName)
}
if tableConfig.PageSize <= 0 {
return fmt.Errorf("table %s has invalid page size", tableName)
}
// Validate field configurations
for fieldName, fieldConfig := range tableConfig.Fields {
if fieldConfig.Type == "" {
return fmt.Errorf("field %s in table %s has empty type", fieldName, tableName)
}
}
}
s.logger.Info("configuration validation completed successfully")
return nil
}
// GetTableConfig returns the configuration for a specific table
func (s *DataService) GetTableConfig(tableName string) (*model.TableConfig, error) {
return s.repo.GetTableConfig(tableName)
}
// GetDefaultTable returns the first configured table name
func (s *DataService) GetDefaultTable() (string, error) {
if len(s.config.Tables) == 0 {
return "", fmt.Errorf("no tables configured")
}
// Return the first table name
for tableName := range s.config.Tables {
return tableName, nil
}
return "", fmt.Errorf("no tables configured")
}