// application/timetracking/create_time_entry.go package main import ( "context" "time" "github.com/google/uuid" "github.com/username/timetracker/internal/domain/entities" "github.com/username/timetracker/internal/domain/repositories" "github.com/username/timetracker/pkg/functional" "github.com/username/timetracker/pkg/validator" ) // CreateTimeEntryCommand enthält die Daten zum Erstellen einer Zeitbuchung type CreateTimeEntryCommand struct { UserID uuid.UUID ProjectID uuid.UUID ActivityID uuid.UUID TaskID *uuid.UUID StartTime time.Time EndTime time.Time Description string BillablePercentage int } // CreateTimeEntryUseCase repräsentiert den Anwendungsfall zum Erstellen einer Zeitbuchung type CreateTimeEntryUseCase struct { timeEntryRepo repositories.TimeEntryRepository projectRepo repositories.ProjectRepository activityRepo repositories.ActivityRepository userRepo repositories.UserRepository } // NewCreateTimeEntryUseCase erstellt eine neue Instanz des UseCase func NewCreateTimeEntryUseCase( timeEntryRepo repositories.TimeEntryRepository, projectRepo repositories.ProjectRepository, activityRepo repositories.ActivityRepository, userRepo repositories.UserRepository, ) *CreateTimeEntryUseCase { return &CreateTimeEntryUseCase{ timeEntryRepo: timeEntryRepo, projectRepo: projectRepo, activityRepo: activityRepo, userRepo: userRepo, } } // Execute führt den Anwendungsfall aus func (uc *CreateTimeEntryUseCase) Execute(ctx context.Context, companyID uuid.UUID, cmd CreateTimeEntryCommand) functional.Result[*entities.TimeEntry] { // Validierung if err := validator.ValidateStruct(cmd); err != nil { return functional.Failure[*entities.TimeEntry](err) } // Überprüfen, ob Projekt existiert und zum gleichen Tenant gehört projectResult := uc.projectRepo.FindByID(ctx, companyID, cmd.ProjectID) if projectResult.IsFailure() { return functional.Failure[*entities.TimeEntry](projectResult.Error()) } // Überprüfen, ob Activity existiert und zum gleichen Tenant gehört activityResult := uc.activityRepo.FindByID(ctx, companyID, cmd.ActivityID) if activityResult.IsFailure() { return functional.Failure[*entities.TimeEntry](activityResult.Error()) } activity := activityResult.Value() // Benutzer abrufen für den Stundensatz userResult := uc.userRepo.FindByID(ctx, companyID, cmd.UserID) if userResult.IsFailure() { return functional.Failure[*entities.TimeEntry](userResult.Error()) } user := userResult.Value() // Berechnung der Dauer in Minuten durationMinutes := int(cmd.EndTime.Sub(cmd.StartTime).Minutes()) // TimeEntry erstellen timeEntry := &entities.TimeEntry{ TenantEntity: entities.TenantEntity{ CompanyID: companyID, }, UserID: cmd.UserID, ProjectID: cmd.ProjectID, ActivityID: cmd.ActivityID, TaskID: cmd.TaskID, StartTime: cmd.StartTime, EndTime: cmd.EndTime, DurationMinutes: durationMinutes, Description: cmd.Description, BillablePercentage: cmd.BillablePercentage, BillingRate: activity.BillingRate, } // Speichern der TimeEntry return uc.timeEntryRepo.Create(ctx, timeEntry) }