package ds import ( "context" "github.com/oklog/ulid/v2" "github.com/timetracker/backend/internal/domain/entities" "github.com/timetracker/backend/internal/domain/persistence" "github.com/timetracker/backend/internal/infrastructure/persistence/db/dbo" "gorm.io/gorm" ) type UserDatasource struct { db *gorm.DB } func NewUserDatasource(db *gorm.DB) persistence.UserDatasource { return &UserDatasource{db: db} } func (r *UserDatasource) Get(ctx context.Context, id ulid.ULID) (*entities.User, error) { var userDBO dbo.UserDBO if err := r.db.WithContext(ctx).First(&userDBO, "id = ?", id).Error; err != nil { return nil, err } user := &entities.User{ EntityBase: entities.EntityBase{ ID: userDBO.ID, CreatedAt: userDBO.CreatedAt, UpdatedAt: userDBO.UpdatedAt, }, Email: userDBO.Email, Salt: userDBO.Salt, Role: userDBO.Role, CompanyID: userDBO.CompanyID, HourlyRate: userDBO.HourlyRate, } return user, nil } func (r *UserDatasource) Create(ctx context.Context, user *entities.User, passwordHash string, salt string) error { old := r.db.WithContext(ctx).First(&dbo.UserDBO{}, "email = ?", user.Email) if old.Error == nil { return entities.ErrUserAlreadyExists } userDBO := dbo.UserDBO{ ID: user.ID, CreatedAt: user.CreatedAt, UpdatedAt: user.UpdatedAt, Email: user.Email, PasswordHash: passwordHash, Salt: salt, Role: user.Role, CompanyID: user.CompanyID, HourlyRate: user.HourlyRate, } return r.db.WithContext(ctx).Create(&userDBO).Error } func (r *UserDatasource) Update(ctx context.Context, user *entities.User, passwordHash *string) error { var existingUser dbo.UserDBO if err := r.db.WithContext(ctx).First(&existingUser, "id = ?", user.ID).Error; err != nil { return entities.ErrUserNotFound } // Nur relevante Felder aktualisieren updateData := map[string]interface{}{ "email": user.Email, "role": user.Role, "company_id": user.CompanyID, "hourly_rate": user.HourlyRate, "updated_at": gorm.Expr("NOW()"), // Optional: Automatisch das Update-Datum setzen } if passwordHash != nil { updateData["password_hash"] = *passwordHash } return r.db.WithContext(ctx).Model(&dbo.UserDBO{}).Where("id = ?", user.ID).Updates(updateData).Error } func (r *UserDatasource) Delete(ctx context.Context, id ulid.ULID) error { return r.db.WithContext(ctx).Delete(&dbo.UserDBO{}, "id = ?", id).Error } func (r *UserDatasource) GetByEmail(ctx context.Context, email string) (*entities.User, error) { var userDBO dbo.UserDBO if err := r.db.WithContext(ctx).Where("email = ?", email).First(&userDBO).Error; err != nil { return nil, err } user := &entities.User{ EntityBase: entities.EntityBase{ ID: userDBO.ID, CreatedAt: userDBO.CreatedAt, UpdatedAt: userDBO.UpdatedAt, }, Email: userDBO.Email, Salt: userDBO.Salt, Role: userDBO.Role, CompanyID: userDBO.CompanyID, HourlyRate: userDBO.HourlyRate, } return user, nil }