Automated Action 887703b6a2 Add Go Todo App implementation
This commit adds a complete Go implementation of the Todo application. The
application uses Gin framework for the web server, GORM for database access,
and SQLite for storage.

Key features:
- Todo CRUD operations with the same API endpoints
- Health check endpoint
- Database migrations
- Tests for models, services, and API handlers
- Documentation for the API
- Configurable settings
2025-05-17 22:20:05 +00:00

126 lines
2.9 KiB
Go

package service
import (
"errors"
"fmt"
"github.com/simpletodoapp/go-todo-app/internal/dto"
"github.com/simpletodoapp/go-todo-app/internal/model"
"gorm.io/gorm"
)
// TodoService handles todo operations
type TodoService struct {
db *gorm.DB
}
// NewTodoService creates a new todo service
func NewTodoService(db *gorm.DB) *TodoService {
return &TodoService{db: db}
}
// GetTodos retrieves todos with optional filters and pagination
func (s *TodoService) GetTodos(skip, limit int, completed *bool) ([]model.Todo, error) {
var todos []model.Todo
query := s.db
// Apply completed filter if provided
if completed != nil {
query = query.Where("completed = ?", *completed)
}
// Apply pagination
result := query.Offset(skip).Limit(limit).Find(&todos)
if result.Error != nil {
return nil, fmt.Errorf("error getting todos: %v", result.Error)
}
return todos, nil
}
// GetTodoByID retrieves a specific todo by ID
func (s *TodoService) GetTodoByID(id uint) (*model.Todo, error) {
var todo model.Todo
result := s.db.First(&todo, id)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil // Todo not found, but not an error
}
return nil, fmt.Errorf("error getting todo: %v", result.Error)
}
return &todo, nil
}
// CreateTodo creates a new todo
func (s *TodoService) CreateTodo(todoCreate dto.TodoCreate) (*model.Todo, error) {
todo := model.Todo{
Title: todoCreate.Title,
Description: todoCreate.Description,
Completed: todoCreate.Completed,
}
result := s.db.Create(&todo)
if result.Error != nil {
return nil, fmt.Errorf("error creating todo: %v", result.Error)
}
return &todo, nil
}
// UpdateTodo updates an existing todo
func (s *TodoService) UpdateTodo(id uint, todoUpdate dto.TodoUpdate) (*model.Todo, error) {
// Get existing todo
todo, err := s.GetTodoByID(id)
if err != nil {
return nil, err
}
if todo == nil {
return nil, nil // Not found
}
// Update fields if provided
updates := map[string]interface{}{}
if todoUpdate.Title != nil {
updates["title"] = *todoUpdate.Title
}
if todoUpdate.Description != nil {
updates["description"] = *todoUpdate.Description
}
if todoUpdate.Completed != nil {
updates["completed"] = *todoUpdate.Completed
}
// Apply updates
result := s.db.Model(&todo).Updates(updates)
if result.Error != nil {
return nil, fmt.Errorf("error updating todo: %v", result.Error)
}
// Refresh the todo from database
return s.GetTodoByID(id)
}
// DeleteTodo deletes a todo by ID
func (s *TodoService) DeleteTodo(id uint) (bool, error) {
// Check if todo exists
todo, err := s.GetTodoByID(id)
if err != nil {
return false, err
}
if todo == nil {
return false, nil // Not found
}
// Delete the todo
result := s.db.Delete(&model.Todo{}, id)
if result.Error != nil {
return false, fmt.Errorf("error deleting todo: %v", result.Error)
}
return true, nil
}