Mhamdans17 commited on
Commit ·
a66f5d3
1
Parent(s): 7cfb539
feat: track member creation details and point history log
Browse files- controllers/member_controller.go +40 -6
- controllers/order_controller.go +8 -0
- main.go +2 -0
- models/models.go +19 -3
controllers/member_controller.go
CHANGED
|
@@ -19,7 +19,7 @@ func ListMembers(c *gin.Context) {
|
|
| 19 |
companyID := *user.CompanyID
|
| 20 |
|
| 21 |
var members []models.Member
|
| 22 |
-
if err := config.DB.Where("company_id = ?", companyID).Order("created_at desc").Find(&members).Error; err != nil {
|
| 23 |
c.JSON(http.StatusInternalServerError, gin.H{"detail": "Gagal mengambil data member"})
|
| 24 |
return
|
| 25 |
}
|
|
@@ -56,11 +56,13 @@ func CreateMember(c *gin.Context) {
|
|
| 56 |
}
|
| 57 |
|
| 58 |
newMember := models.Member{
|
| 59 |
-
CompanyID:
|
| 60 |
-
MemberCode:
|
| 61 |
-
Name:
|
| 62 |
-
Phone:
|
| 63 |
-
Points:
|
|
|
|
|
|
|
| 64 |
}
|
| 65 |
|
| 66 |
if err := config.DB.Create(&newMember).Error; err != nil {
|
|
@@ -135,6 +137,8 @@ func SetPoints(c *gin.Context) {
|
|
| 135 |
return
|
| 136 |
}
|
| 137 |
|
|
|
|
|
|
|
| 138 |
member.Points = input.Points
|
| 139 |
|
| 140 |
if err := config.DB.Save(&member).Error; err != nil {
|
|
@@ -142,9 +146,39 @@ func SetPoints(c *gin.Context) {
|
|
| 142 |
return
|
| 143 |
}
|
| 144 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 145 |
c.JSON(http.StatusOK, member)
|
| 146 |
}
|
| 147 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
// DeleteMember (DELETE /api/members/:member_id)
|
| 149 |
func DeleteMember(c *gin.Context) {
|
| 150 |
userVal, exists := c.Get("user")
|
|
|
|
| 19 |
companyID := *user.CompanyID
|
| 20 |
|
| 21 |
var members []models.Member
|
| 22 |
+
if err := config.DB.Preload("Branch").Preload("CreatedBy").Where("company_id = ?", companyID).Order("created_at desc").Find(&members).Error; err != nil {
|
| 23 |
c.JSON(http.StatusInternalServerError, gin.H{"detail": "Gagal mengambil data member"})
|
| 24 |
return
|
| 25 |
}
|
|
|
|
| 56 |
}
|
| 57 |
|
| 58 |
newMember := models.Member{
|
| 59 |
+
CompanyID: companyID,
|
| 60 |
+
MemberCode: input.MemberID,
|
| 61 |
+
Name: input.Name,
|
| 62 |
+
Phone: input.Phone,
|
| 63 |
+
Points: 0,
|
| 64 |
+
CreatedByID: &user.ID,
|
| 65 |
+
BranchID: user.BranchID,
|
| 66 |
}
|
| 67 |
|
| 68 |
if err := config.DB.Create(&newMember).Error; err != nil {
|
|
|
|
| 137 |
return
|
| 138 |
}
|
| 139 |
|
| 140 |
+
delta := input.Points - member.Points
|
| 141 |
+
|
| 142 |
member.Points = input.Points
|
| 143 |
|
| 144 |
if err := config.DB.Save(&member).Error; err != nil {
|
|
|
|
| 146 |
return
|
| 147 |
}
|
| 148 |
|
| 149 |
+
if delta != 0 {
|
| 150 |
+
history := models.PointHistory{
|
| 151 |
+
CompanyID: companyID,
|
| 152 |
+
MemberID: member.ID,
|
| 153 |
+
PointsDelta: delta,
|
| 154 |
+
Reason: "Penyesuaian manual oleh " + user.Name,
|
| 155 |
+
}
|
| 156 |
+
config.DB.Create(&history)
|
| 157 |
+
}
|
| 158 |
+
|
| 159 |
c.JSON(http.StatusOK, member)
|
| 160 |
}
|
| 161 |
|
| 162 |
+
// GetPointHistory (GET /api/members/:member_id/points/history)
|
| 163 |
+
func GetPointHistory(c *gin.Context) {
|
| 164 |
+
userVal, exists := c.Get("user")
|
| 165 |
+
if !exists {
|
| 166 |
+
c.JSON(http.StatusUnauthorized, gin.H{"detail": "Unauthorized"})
|
| 167 |
+
return
|
| 168 |
+
}
|
| 169 |
+
user := userVal.(*models.User)
|
| 170 |
+
companyID := *user.CompanyID
|
| 171 |
+
memberID := c.Param("member_id")
|
| 172 |
+
|
| 173 |
+
var history []models.PointHistory
|
| 174 |
+
if err := config.DB.Where("company_id = ? AND member_id = ?", companyID, memberID).Order("created_at desc").Find(&history).Error; err != nil {
|
| 175 |
+
c.JSON(http.StatusInternalServerError, gin.H{"detail": "Gagal mengambil riwayat poin"})
|
| 176 |
+
return
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
c.JSON(http.StatusOK, history)
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
// DeleteMember (DELETE /api/members/:member_id)
|
| 183 |
func DeleteMember(c *gin.Context) {
|
| 184 |
userVal, exists := c.Get("user")
|
controllers/order_controller.go
CHANGED
|
@@ -980,6 +980,14 @@ func awardPoints(tx *gorm.DB, order *models.Order, company *models.Company) {
|
|
| 980 |
order.PointsEarned = pointsToAdd
|
| 981 |
order.Member = &member
|
| 982 |
tx.Save(order)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 983 |
|
| 984 |
log.Printf("[POINTS] Member %s (+%d poin dari transaksi %d berdasarkan rule min %d)", member.Name, pointsToAdd, order.TotalAmount, matchedRule.MinAmount)
|
| 985 |
}
|
|
|
|
| 980 |
order.PointsEarned = pointsToAdd
|
| 981 |
order.Member = &member
|
| 982 |
tx.Save(order)
|
| 983 |
+
|
| 984 |
+
history := models.PointHistory{
|
| 985 |
+
CompanyID: company.ID,
|
| 986 |
+
MemberID: member.ID,
|
| 987 |
+
PointsDelta: pointsToAdd,
|
| 988 |
+
Reason: "Poin dari transaksi " + order.OrderNumber,
|
| 989 |
+
}
|
| 990 |
+
tx.Create(&history)
|
| 991 |
|
| 992 |
log.Printf("[POINTS] Member %s (+%d poin dari transaksi %d berdasarkan rule min %d)", member.Name, pointsToAdd, order.TotalAmount, matchedRule.MinAmount)
|
| 993 |
}
|
main.go
CHANGED
|
@@ -39,6 +39,7 @@ func main() {
|
|
| 39 |
&models.PointRule{},
|
| 40 |
&models.WalletTransaction{},
|
| 41 |
&models.TopupRequest{},
|
|
|
|
| 42 |
)
|
| 43 |
if err != nil {
|
| 44 |
log.Fatalf("Gagal melakukan Auto-Migration: %v", err)
|
|
@@ -160,6 +161,7 @@ func main() {
|
|
| 160 |
members.POST("/", controllers.CreateMember)
|
| 161 |
members.PUT("/:member_id", controllers.UpdateMember)
|
| 162 |
members.PUT("/:member_id/points", middleware.RequireOwner(), controllers.SetPoints)
|
|
|
|
| 163 |
members.DELETE("/:member_id", middleware.RequireOwner(), controllers.DeleteMember)
|
| 164 |
}
|
| 165 |
}
|
|
|
|
| 39 |
&models.PointRule{},
|
| 40 |
&models.WalletTransaction{},
|
| 41 |
&models.TopupRequest{},
|
| 42 |
+
&models.PointHistory{},
|
| 43 |
)
|
| 44 |
if err != nil {
|
| 45 |
log.Fatalf("Gagal melakukan Auto-Migration: %v", err)
|
|
|
|
| 161 |
members.POST("/", controllers.CreateMember)
|
| 162 |
members.PUT("/:member_id", controllers.UpdateMember)
|
| 163 |
members.PUT("/:member_id/points", middleware.RequireOwner(), controllers.SetPoints)
|
| 164 |
+
members.GET("/:member_id/points/history", controllers.GetPointHistory)
|
| 165 |
members.DELETE("/:member_id", middleware.RequireOwner(), controllers.DeleteMember)
|
| 166 |
}
|
| 167 |
}
|
models/models.go
CHANGED
|
@@ -53,9 +53,25 @@ type Member struct {
|
|
| 53 |
MemberCode string `gorm:"column:member_id;type:varchar(50);not null;uniqueIndex:uq_company_member" json:"member_id"`
|
| 54 |
Name string `gorm:"type:varchar(100);not null" json:"name"`
|
| 55 |
Phone string `gorm:"type:varchar(20)" json:"phone"`
|
| 56 |
-
Points
|
| 57 |
-
|
| 58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
}
|
| 60 |
|
| 61 |
type Branch struct {
|
|
|
|
| 53 |
MemberCode string `gorm:"column:member_id;type:varchar(50);not null;uniqueIndex:uq_company_member" json:"member_id"`
|
| 54 |
Name string `gorm:"type:varchar(100);not null" json:"name"`
|
| 55 |
Phone string `gorm:"type:varchar(20)" json:"phone"`
|
| 56 |
+
Points int `gorm:"default:0" json:"points"`
|
| 57 |
+
BranchID *uint `gorm:"index" json:"branch_id"`
|
| 58 |
+
CreatedByID *uint `gorm:"index" json:"created_by_id"`
|
| 59 |
+
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
|
| 60 |
+
Company *Company `gorm:"foreignKey:CompanyID" json:"company,omitempty"`
|
| 61 |
+
Branch *Branch `gorm:"foreignKey:BranchID" json:"branch,omitempty"`
|
| 62 |
+
CreatedBy *User `gorm:"foreignKey:CreatedByID" json:"created_by,omitempty"`
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
type PointHistory struct {
|
| 66 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 67 |
+
CompanyID uint `gorm:"not null;index" json:"company_id"`
|
| 68 |
+
MemberID uint `gorm:"not null;index" json:"member_id"`
|
| 69 |
+
PointsDelta int `gorm:"not null" json:"points_delta"` // e.g. +5 or -2
|
| 70 |
+
Reason string `gorm:"type:varchar(255)" json:"reason"` // e.g., "Transaksi WP-123", "Penyesuaian Manual oleh Budi"
|
| 71 |
+
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
|
| 72 |
+
|
| 73 |
+
Company *Company `gorm:"foreignKey:CompanyID" json:"-"`
|
| 74 |
+
Member *Member `gorm:"foreignKey:MemberID" json:"-"`
|
| 75 |
}
|
| 76 |
|
| 77 |
type Branch struct {
|