package controllers import ( "net/http" "service-warungpos-go/config" "service-warungpos-go/models" "github.com/gin-gonic/gin" "gorm.io/gorm" ) // ListMembers (GET /api/members) func ListMembers(c *gin.Context) { userVal, exists := c.Get("user") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"detail": "Unauthorized"}) return } user := userVal.(*models.User) companyID := *user.CompanyID var members []models.Member if err := config.DB.Preload("Branch").Preload("CreatedBy").Where("company_id = ?", companyID).Order("created_at desc").Find(&members).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"detail": "Gagal mengambil data member"}) return } c.JSON(http.StatusOK, members) } // CreateMember (POST /api/members) func CreateMember(c *gin.Context) { userVal, exists := c.Get("user") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"detail": "Unauthorized"}) return } user := userVal.(*models.User) companyID := *user.CompanyID var input struct { MemberID string `json:"member_id" binding:"required"` Name string `json:"name" binding:"required"` Phone string `json:"phone"` CreatedByName string `json:"created_by_name"` } if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"detail": "Data tidak valid", "error": err.Error()}) return } // Cek apakah member_id sudah dipakai di company ini var existing models.Member if err := config.DB.Where("company_id = ? AND member_id = ?", companyID, input.MemberID).First(&existing).Error; err == nil { c.JSON(http.StatusBadRequest, gin.H{"detail": "ID Member sudah digunakan"}) return } newMember := models.Member{ CompanyID: companyID, MemberCode: input.MemberID, Name: input.Name, Phone: input.Phone, Points: 0, CreatedByID: &user.ID, CreatedByName: input.CreatedByName, BranchID: user.BranchID, } if err := config.DB.Create(&newMember).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"detail": "Gagal membuat member"}) return } c.JSON(http.StatusCreated, newMember) } // UpdateMember (PUT /api/members/:member_id) func UpdateMember(c *gin.Context) { userVal, exists := c.Get("user") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"detail": "Unauthorized"}) return } user := userVal.(*models.User) companyID := *user.CompanyID memberID := c.Param("member_id") var member models.Member if err := config.DB.Where("company_id = ? AND id = ?", companyID, memberID).First(&member).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"detail": "Member tidak ditemukan"}) return } var input struct { Name string `json:"name" binding:"required"` Phone string `json:"phone"` } if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"detail": "Data tidak valid"}) return } member.Name = input.Name member.Phone = input.Phone if err := config.DB.Save(&member).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"detail": "Gagal update member"}) return } c.JSON(http.StatusOK, member) } // SetPoints (PUT /api/members/:member_id/points) - Owner ONLY func SetPoints(c *gin.Context) { userVal, exists := c.Get("user") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"detail": "Unauthorized"}) return } user := userVal.(*models.User) companyID := *user.CompanyID memberID := c.Param("member_id") var member models.Member if err := config.DB.Where("company_id = ? AND id = ?", companyID, memberID).First(&member).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"detail": "Member tidak ditemukan"}) return } var input struct { Points int `json:"points"` } if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"detail": "Data tidak valid"}) return } delta := input.Points - member.Points member.Points = input.Points if err := config.DB.Save(&member).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"detail": "Gagal update poin"}) return } if delta != 0 { var branch models.Branch branchName := "Pusat" if user.BranchID != nil { if err := config.DB.First(&branch, *user.BranchID).Error; err == nil { branchName = branch.Name } } history := models.PointHistory{ CompanyID: companyID, MemberID: member.ID, PointsDelta: delta, Reason: "Penyesuaian manual oleh " + user.Name + " (Cabang " + branchName + ")", } config.DB.Create(&history) } c.JSON(http.StatusOK, member) } // GetPointHistory (GET /api/members/:member_id/points/history) func GetPointHistory(c *gin.Context) { userVal, exists := c.Get("user") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"detail": "Unauthorized"}) return } user := userVal.(*models.User) companyID := *user.CompanyID memberID := c.Param("member_id") var history []models.PointHistory if err := config.DB.Where("company_id = ? AND member_id = ?", companyID, memberID).Order("created_at desc").Find(&history).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"detail": "Gagal mengambil riwayat poin"}) return } c.JSON(http.StatusOK, history) } // DeleteMember (DELETE /api/members/:member_id) func DeleteMember(c *gin.Context) { userVal, exists := c.Get("user") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"detail": "Unauthorized"}) return } user := userVal.(*models.User) companyID := *user.CompanyID memberID := c.Param("member_id") if err := config.DB.Where("company_id = ? AND id = ?", companyID, memberID).Delete(&models.Member{}).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"detail": "Gagal menghapus member"}) return } c.JSON(http.StatusOK, gin.H{"detail": "Member dihapus"}) } // CheckMember (GET /api/members/check?query=xxx) func CheckMember(c *gin.Context) { userVal, exists := c.Get("user") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"detail": "Unauthorized"}) return } user := userVal.(*models.User) companyID := *user.CompanyID query := c.Query("query") if query == "" { c.JSON(http.StatusBadRequest, gin.H{"detail": "Query pencarian wajib diisi"}) return } var member models.Member if err := config.DB.Preload("Branch").Preload("CreatedBy").Preload("PointHistories", func(db *gorm.DB) *gorm.DB { return db.Order("created_at DESC").Limit(10) }).Where("company_id = ? AND (member_id = ? OR phone = ?)", companyID, query, query).First(&member).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"detail": "Member tidak ditemukan"}) return } c.JSON(http.StatusOK, member) }