add users

This commit is contained in:
Aditya Siregar
2025-08-15 22:17:01 +07:00
parent 826c5d26ad
commit e1a5e9efd3
13 changed files with 272 additions and 34 deletions
+93
View File
@@ -312,3 +312,96 @@ func (p *UserProcessorImpl) GetActiveUsersForMention(ctx context.Context, search
return responses, nil
}
// BulkCreateUsersWithTransaction creates multiple users in a transaction with proper error handling
func (p *UserProcessorImpl) BulkCreateUsersWithTransaction(ctx context.Context, userRequests []contract.BulkUserRequest) ([]contract.UserResponse, []contract.BulkUserErrorResult, error) {
created := []contract.UserResponse{}
failed := []contract.BulkUserErrorResult{}
// Pre-validate all users
usersToCreate := []*entities.User{}
emailMap := make(map[string]bool)
for _, req := range userRequests {
// Check for duplicate emails in the batch
if emailMap[req.Email] {
failed = append(failed, contract.BulkUserErrorResult{
User: req,
Error: "Duplicate email in batch",
})
continue
}
emailMap[req.Email] = true
// Check if email already exists in database
existing, _ := p.userRepo.GetByEmail(ctx, req.Email)
if existing != nil {
failed = append(failed, contract.BulkUserErrorResult{
User: req,
Error: "Email already exists",
})
continue
}
// Hash password
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
if err != nil {
failed = append(failed, contract.BulkUserErrorResult{
User: req,
Error: "Failed to hash password",
})
continue
}
// Create user entity
user := &entities.User{
ID: uuid.New(),
Name: req.Name,
Email: req.Email,
PasswordHash: string(hashedPassword),
IsActive: true,
}
usersToCreate = append(usersToCreate, user)
}
// Bulk create valid users
if len(usersToCreate) > 0 {
// Use CreateInBatches for large datasets
err := p.userRepo.CreateInBatches(ctx, usersToCreate, 50)
if err != nil {
// If bulk creation fails, try individual creation
for i, user := range usersToCreate {
err := p.userRepo.Create(ctx, user)
if err != nil {
failed = append(failed, contract.BulkUserErrorResult{
User: userRequests[i],
Error: err.Error(),
})
} else {
// Create default profile for the user
profile := &entities.UserProfile{
UserID: user.ID,
FullName: user.Name,
}
_ = p.profileRepo.Create(ctx, profile)
created = append(created, *transformer.EntityToContract(user))
}
}
} else {
// Create profiles for all successfully created users
for _, user := range usersToCreate {
profile := &entities.UserProfile{
UserID: user.ID,
FullName: user.Name,
}
_ = p.profileRepo.Create(ctx, profile)
created = append(created, *transformer.EntityToContract(user))
}
}
}
return created, failed, nil
}
+4
View File
@@ -27,4 +27,8 @@ type UserRepository interface {
// New optimized helpers
GetRolesByUserIDs(ctx context.Context, userIDs []uuid.UUID) (map[uuid.UUID][]entities.Role, error)
ListWithFilters(ctx context.Context, search *string, roleCode *string, isActive *bool, limit, offset int) ([]*entities.User, int64, error)
// Bulk operations
BulkCreate(ctx context.Context, users []*entities.User) error
CreateInBatches(ctx context.Context, users []*entities.User, batchSize int) error
}