// interfaces/http/handlers/time_entry_handler.go package main import ( "net/http" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/username/timetracker/internal/application/timetracking" "github.com/username/timetracker/internal/interfaces/http/dto" "github.com/username/timetracker/internal/interfaces/http/middleware" ) // TimeEntryHandler behandelt HTTP-Anfragen für Zeitbuchungen type TimeEntryHandler struct { createTimeEntryUseCase *timetracking.CreateTimeEntryUseCase updateTimeEntryUseCase *timetracking.UpdateTimeEntryUseCase listTimeEntriesUseCase *timetracking.ListTimeEntriesUseCase deleteTimeEntryUseCase *timetracking.DeleteTimeEntryUseCase } // NewTimeEntryHandler erstellt einen neuen TimeEntryHandler func NewTimeEntryHandler( createTimeEntryUseCase *timetracking.CreateTimeEntryUseCase, updateTimeEntryUseCase *timetracking.UpdateTimeEntryUseCase, listTimeEntriesUseCase *timetracking.ListTimeEntriesUseCase, deleteTimeEntryUseCase *timetracking.DeleteTimeEntryUseCase, ) *TimeEntryHandler { return &TimeEntryHandler{ createTimeEntryUseCase: createTimeEntryUseCase, updateTimeEntryUseCase: updateTimeEntryUseCase, listTimeEntriesUseCase: listTimeEntriesUseCase, deleteTimeEntryUseCase: deleteTimeEntryUseCase, } } // RegisterRoutes registriert die Routen am Router func (h *TimeEntryHandler) RegisterRoutes(router *gin.RouterGroup) { timeEntries := router.Group("/time-entries") { timeEntries.GET("", h.ListTimeEntries) timeEntries.POST("", h.CreateTimeEntry) timeEntries.GET("/:id", h.GetTimeEntry) timeEntries.PUT("/:id", h.UpdateTimeEntry) timeEntries.DELETE("/:id", h.DeleteTimeEntry) } } // CreateTimeEntry behandelt die Erstellung einer neuen Zeitbuchung func (h *TimeEntryHandler) CreateTimeEntry(c *gin.Context) { var req dto.CreateTimeEntryRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // Tenant-ID aus dem Kontext extrahieren companyID, exists := middleware.GetCompanyID(c) if !exists { c.JSON(http.StatusBadRequest, gin.H{"error": "Company ID not found"}) return } // Benutzer-ID aus dem Kontext oder Request var userID uuid.UUID if req.UserID != nil { userID = *req.UserID } else { currentUserID, exists := middleware.GetUserID(c) if !exists { c.JSON(http.StatusBadRequest, gin.H{"error": "User ID not found"}) return } userID = currentUserID } // Command erstellen cmd := timetracking.CreateTimeEntryCommand{ UserID: userID, ProjectID: req.ProjectID, ActivityID: req.ActivityID, TaskID: req.TaskID, StartTime: req.StartTime, EndTime: req.EndTime, Description: req.Description, BillablePercentage: req.BillablePercentage, } // UseCase ausführen result := h.createTimeEntryUseCase.Execute(c.Request.Context(), companyID, cmd) if result.IsFailure() { c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error().Error()}) return } // TimeEntry in Response-DTO umwandeln timeEntry := result.Value() response := dto.MapTimeEntryToDTO(*timeEntry) c.JSON(http.StatusCreated, response) }