This commit is contained in:
[Valentino Heman Budiarto] 2026-03-05 15:22:15 +07:00
parent 9d4cc8bfed
commit bad2d21fc2
3 changed files with 49 additions and 25 deletions

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"s-class-backend/config" "s-class-backend/config"
"s-class-backend/helpers" // Import helper pembuat kode acak
"s-class-backend/models" "s-class-backend/models"
"time" "time"
@ -25,15 +26,13 @@ func CreateBooking(c *gin.Context) {
return return
} }
// --- PERBAIKAN DI SINI (Handle UUID) --- // --- Handle UUID ---
// Ambil user_id dari context (hasil login)
userIDInterface, exists := c.Get("user_id") userIDInterface, exists := c.Get("user_id")
if !exists { if !exists {
c.JSON(http.StatusUnauthorized, gin.H{"error": "User ID tidak ditemukan"}) c.JSON(http.StatusUnauthorized, gin.H{"error": "User ID tidak ditemukan"})
return return
} }
// Konversi interface{} ke string dulu, baru ke UUID
userIDStr, ok := userIDInterface.(string) userIDStr, ok := userIDInterface.(string)
if !ok { if !ok {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Format User ID token salah"}) c.JSON(http.StatusInternalServerError, gin.H{"error": "Format User ID token salah"})
@ -45,7 +44,6 @@ func CreateBooking(c *gin.Context) {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Gagal memproses User ID"}) c.JSON(http.StatusInternalServerError, gin.H{"error": "Gagal memproses User ID"})
return return
} }
// ---------------------------------------
// Validasi Waktu // Validasi Waktu
if input.EndTime.Before(input.StartTime) { if input.EndTime.Before(input.StartTime) {
@ -73,9 +71,8 @@ func CreateBooking(c *gin.Context) {
Status: "Pending", Status: "Pending",
} }
// Tampilkan error asli database jika gagal
if err := config.DB.Create(&booking).Error; err != nil { if err := config.DB.Create(&booking).Error; err != nil {
fmt.Println("Error DB:", err) // Print error ke terminal fmt.Println("Error DB:", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return return
} }
@ -85,23 +82,19 @@ func CreateBooking(c *gin.Context) {
"data": booking, "data": booking,
}) })
} }
func GetUserBookings(c *gin.Context) { func GetUserBookings(c *gin.Context) {
var bookings []models.Booking var bookings []models.Booking
// 1. Ambil User ID dan Role dari token yang sedang login
userID, _ := c.Get("user_id") userID, _ := c.Get("user_id")
role, _ := c.Get("role") role, _ := c.Get("role")
// 2. Cek apakah dia Admin
if role == "admin" { if role == "admin" {
// Jika ADMIN: Ambil SEMUA data peminjaman dari semua user, urutkan dari yang terbaru
// Kita juga ambil data Room dan User agar detailnya lengkap
if err := config.DB.Preload("Room").Preload("User").Order("created_at desc").Find(&bookings).Error; err != nil { if err := config.DB.Preload("Room").Preload("User").Order("created_at desc").Find(&bookings).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return return
} }
} else { } else {
// Jika MAHASISWA: Ambil HANYA data peminjaman miliknya sendiri
if err := config.DB.Preload("Room").Where("user_id = ?", userID).Order("created_at desc").Find(&bookings).Error; err != nil { if err := config.DB.Preload("Room").Where("user_id = ?", userID).Order("created_at desc").Find(&bookings).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return return
@ -112,30 +105,38 @@ func GetUserBookings(c *gin.Context) {
} }
type UpdateStatusInput struct { type UpdateStatusInput struct {
Status string `json:"status" binding:"required"` // Isinya: 'Approved', 'Rejected', 'Completed', 'Cancelled' Status string `json:"status" binding:"required"`
} }
// --- FUNGSI 3: UPDATE STATUS (ADMIN) --- // --- FUNGSI UPDATE STATUS (ADMIN) ---
func UpdateBookingStatus(c *gin.Context) { func UpdateBookingStatus(c *gin.Context) {
// 1. Ambil ID Booking dari URL (misal: /bookings/123)
bookingID := c.Param("id") bookingID := c.Param("id")
// 2. Cek apakah booking ada?
var booking models.Booking var booking models.Booking
if err := config.DB.First(&booking, "booking_id = ?", bookingID).Error; err != nil { if err := config.DB.First(&booking, "booking_id = ?", bookingID).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Booking tidak ditemukan"}) c.JSON(http.StatusNotFound, gin.H{"error": "Booking tidak ditemukan"})
return return
} }
// 3. Validasi Input JSON
var input UpdateStatusInput var input UpdateStatusInput
if err := c.ShouldBindJSON(&input); err != nil { if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return return
} }
// 4. Update Status ke Database
booking.Status = input.Status booking.Status = input.Status
// 👇 LOGIKA PEMBUATAN REDEEM CODE 👇
if input.Status == "Approved" {
// Buat kode dari helper jika sebelumnya belum punya kode
if booking.RedeemCode == "" {
booking.RedeemCode = helpers.GenerateRedeemCode()
}
} else if input.Status == "Rejected" || input.Status == "Cancelled" {
// Kosongkan kode jika peminjaman ditolak/dibatalkan
booking.RedeemCode = ""
}
config.DB.Save(&booking) config.DB.Save(&booking)
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{

View File

@ -0,0 +1,21 @@
package helpers
import (
"math/rand"
"time"
)
// GenerateRedeemCode membuat kode unik 6 karakter kombinasi Angka dan Huruf
func GenerateRedeemCode() string {
// Inisialisasi seed random berdasarkan waktu sekarang
rand.Seed(time.Now().UnixNano())
// Karakter yang diizinkan (Kombinasi Huruf Besar dan Angka)
charset := "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
code := make([]byte, 6) // Panjang kode = 6 karakter
for i := range code {
code[i] = charset[rand.Intn(len(charset))]
}
return string(code)
}

View File

@ -30,17 +30,19 @@ type Room struct {
type Booking struct { type Booking struct {
BookingID uuid.UUID `gorm:"type:uuid;default:uuid_generate_v4();primaryKey" json:"booking_id"` BookingID uuid.UUID `gorm:"type:uuid;default:uuid_generate_v4();primaryKey" json:"booking_id"`
// Tambahkan references:UserID UserID uuid.UUID `gorm:"type:uuid;not null" json:"user_id"`
UserID uuid.UUID `gorm:"type:uuid;not null" json:"user_id"` User User `gorm:"foreignKey:UserID;references:UserID" json:"user,omitempty"`
User User `gorm:"foreignKey:UserID;references:UserID" json:"user,omitempty"`
// Tambahkan references:RoomID RoomID uint `gorm:"not null" json:"room_id"`
RoomID uint `gorm:"not null" json:"room_id"` Room Room `gorm:"foreignKey:RoomID;references:RoomID" json:"room"`
Room Room `gorm:"foreignKey:RoomID;references:RoomID" json:"room"`
StartTime time.Time `gorm:"not null" json:"start_time"` StartTime time.Time `gorm:"not null" json:"start_time"`
EndTime time.Time `gorm:"not null" json:"end_time"` EndTime time.Time `gorm:"not null" json:"end_time"`
Purpose string `gorm:"not null" json:"purpose"` Purpose string `gorm:"not null" json:"purpose"`
Status string `gorm:"type:booking_status;default:'Pending'" json:"status"` Status string `gorm:"type:booking_status;default:'Pending'" json:"status"`
// 👇 PASTIKAN BARIS INI ADA DI DALAM SINI 👇
RedeemCode string `gorm:"type:varchar(10)" json:"redeem_code"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
} }