package repositories import ( "gorm.io/gorm" "GoMembership/internal/constants" "GoMembership/internal/database" "gorm.io/gorm/clause" "GoMembership/internal/models" "GoMembership/pkg/errors" "GoMembership/pkg/logger" ) type UserRepositoryInterface interface { CreateUser(user *models.User) (uint, error) UpdateUser(user *models.User) (*models.User, error) GetUsers(where map[string]interface{}) (*[]models.User, error) GetUserByEmail(email string) (*models.User, error) SetVerificationToken(verification *models.Verification) (uint, error) IsVerified(userID *uint) (bool, error) GetVerificationOfToken(token *string) (*models.Verification, error) } type UserRepository struct{} func (ur *UserRepository) CreateUser(user *models.User) (uint, error) { result := database.DB.Create(user) if result.Error != nil { logger.Error.Printf("Create User error: %#v", result.Error) return 0, result.Error } return user.ID, nil } func (ur *UserRepository) UpdateUser(user *models.User) (*models.User, error) { if user == nil { return nil, errors.ErrNoData } err := database.DB.Transaction(func(tx *gorm.DB) error { // Check if the user exists in the database var existingUser models.User if err := tx.Preload("DriversLicence.LicenceCategories"). Preload("Membership"). First(&existingUser, user.ID).Error; err != nil { return err } // Update the user's main fields result := tx.Session(&gorm.Session{FullSaveAssociations: true}).Updates(user) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return errors.ErrNoRowsAffected } // Handle the update of the LicenceCategories explicitly if user.DriversLicence.ID != 0 { // Replace the LicenceCategories with the new list if err := tx.Model(&existingUser.DriversLicence).Association("LicenceCategories").Replace(user.DriversLicence.LicenceCategories); err != nil { return err } } // Update the Membership if provided if user.Membership.ID != 0 { if err := tx.Model(&existingUser.Membership).Updates(user.Membership).Error; err != nil { return err } } // Update the DriversLicence fields if provided if user.DriversLicence.ID != 0 { if err := tx.Model(&existingUser.DriversLicence).Updates(user.DriversLicence).Error; err != nil { return err } } return nil }) if err != nil { return nil, err } var updatedUser models.User if err := database.DB.Preload("DriversLicence.LicenceCategories"). Preload("Membership"). First(&updatedUser, user.ID).Error; err != nil { return nil, err } return &updatedUser, nil } func (ur *UserRepository) GetUsers(where map[string]interface{}) (*[]models.User, error) { var users []models.User result := database.DB. Preload(clause.Associations). Preload("Membership.SubscriptionModel"). Preload("DriversLicence.LicenceCategories"). Where(where).Find(&users) if result.Error != nil { if result.Error == gorm.ErrRecordNotFound { return nil, gorm.ErrRecordNotFound } return nil, result.Error } return &users, nil } func GetUserByID(userID *uint) (*models.User, error) { var user models.User result := database.DB. Preload(clause.Associations). Preload("Membership.SubscriptionModel"). Preload("DriversLicence.LicenceCategories"). First(&user, userID) if result.Error != nil { if result.Error == gorm.ErrRecordNotFound { return nil, gorm.ErrRecordNotFound } return nil, result.Error } return &user, nil } func (ur *UserRepository) GetUserByEmail(email string) (*models.User, error) { var user models.User result := database.DB.Where("email = ?", email).First(&user) if result.Error != nil { if result.Error == gorm.ErrRecordNotFound { return nil, gorm.ErrRecordNotFound } return nil, result.Error } return &user, nil } func (ur *UserRepository) IsVerified(userID *uint) (bool, error) { var user models.User result := database.DB.Select("status").First(&user, userID) if result.Error != nil { if result.Error == gorm.ErrRecordNotFound { return false, gorm.ErrRecordNotFound } return false, result.Error } return user.Status != constants.UnverifiedStatus, nil } func (ur *UserRepository) GetVerificationOfToken(token *string) (*models.Verification, error) { var emailVerification models.Verification result := database.DB.Where("verification_token = ?", token).First(&emailVerification) if result.Error != nil { if result.Error == gorm.ErrRecordNotFound { return nil, gorm.ErrRecordNotFound } return nil, result.Error } return &emailVerification, nil } func (ur *UserRepository) SetVerificationToken(verification *models.Verification) (uint, error) { // Use GORM to insert or update the Verification record result := database.DB.Clauses(clause.OnConflict{ Columns: []clause.Column{{Name: "user_id"}}, DoUpdates: clause.AssignmentColumns([]string{"verification_token", "created_at"}), }).Create(&verification) if result.Error != nil { return 0, result.Error } return verification.ID, nil }