// internal/repositories/user_repo.go - FIXED for ENCRYPTED NRP package repositories import ( "errors" "lost-and-found/internal/models" "gorm.io/gorm" ) type UserRepository struct { db *gorm.DB } func NewUserRepository(db *gorm.DB) *UserRepository { return &UserRepository{db: db} } func (r *UserRepository) Create(user *models.User) error { return r.db.Create(user).Error } func (r *UserRepository) FindByID(id uint) (*models.User, error) { var user models.User // ✅ Tambahkan .Preload("Role.Permissions") err := r.db.Preload("Role").Preload("Role.Permissions").First(&user, id).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("user not found") } return nil, err } return &user, nil } func (r *UserRepository) FindByEmail(email string) (*models.User, error) { var user models.User // ✅ UPDATE: Preload Role DAN Role.Permissions err := r.db. Preload("Role"). Preload("Role.Permissions"). // Memuat daftar hak akses Where("email = ?", email). First(&user).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("user not found") } return nil, err } return &user, nil } // ✅ FIXED: FindByNRP now accepts ENCRYPTED NRP func (r *UserRepository) FindByNRP(nrp string) (*models.User, error) { var user models.User // ✅ UPDATE: Preload Role DAN Role.Permissions err := r.db. Preload("Role"). Preload("Role.Permissions"). // Memuat daftar hak akses Where("nrp = ?", nrp). First(&user).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil // Return nil jika tidak ditemukan (bukan error sistem) } return nil, err } return &user, nil } func (r *UserRepository) FindAll(page, limit int) ([]models.User, int64, error) { var users []models.User var total int64 if err := r.db.Model(&models.User{}).Count(&total).Error; err != nil { return nil, 0, err } offset := (page - 1) * limit err := r.db. Preload("Role"). // Cukup Role saja untuk list view Order("created_at DESC"). Offset(offset).Limit(limit). Find(&users).Error if err != nil { return nil, 0, err } return users, total, nil } func (r *UserRepository) Update(user *models.User) error { return r.db.Save(user).Error } func (r *UserRepository) UpdateRole(userID, roleID uint) error { return r.db.Model(&models.User{}).Where("id = ?", userID).Update("role_id", roleID).Error } func (r *UserRepository) UpdateStatus(userID uint, status string) error { return r.db.Model(&models.User{}).Where("id = ?", userID).Update("status", status).Error } func (r *UserRepository) Delete(id uint) error { return r.db.Delete(&models.User{}, id).Error } func (r *UserRepository) BlockUser(id uint) error { return r.UpdateStatus(id, "blocked") } func (r *UserRepository) UnblockUser(id uint) error { return r.UpdateStatus(id, "active") } func (r *UserRepository) CountByRole(roleID uint) (int64, error) { var count int64 err := r.db.Model(&models.User{}).Where("role_id = ?", roleID).Count(&count).Error return count, err } func (r *UserRepository) GetUserStats(userID uint) (map[string]interface{}, error) { var stats map[string]interface{} = make(map[string]interface{}) // Items reported var itemCount int64 if err := r.db.Model(&models.Item{}). Where("reporter_id = ?", userID).Count(&itemCount).Error; err != nil { return nil, err } stats["items_reported"] = itemCount // Lost items var lostItemCount int64 if err := r.db.Model(&models.LostItem{}). Where("user_id = ?", userID).Count(&lostItemCount).Error; err != nil { return nil, err } stats["lost_items_reported"] = lostItemCount // Claims var claimCount int64 if err := r.db.Model(&models.Claim{}). Where("user_id = ?", userID).Count(&claimCount).Error; err != nil { return nil, err } stats["claims_made"] = claimCount // Approved claims var approvedClaimCount int64 if err := r.db.Model(&models.Claim{}). Where("user_id = ? AND status = ?", userID, models.ClaimStatusApproved). Count(&approvedClaimCount).Error; err != nil { return nil, err } stats["claims_approved"] = approvedClaimCount return stats, nil }