Files
sale/backend/internal/api/handlers/system.go
T
nuyue 74420e687b
Build and Push Docker Image / build-and-push (push) Successful in 1m3s
Build and Push Docker Image / deploy (push) Successful in 7s
fix: add packaging_fee and international_fee_rate to public settings
2026-07-16 16:47:59 +08:00

280 lines
7.2 KiB
Go

package handlers
import (
"fmt"
"net/http"
"strconv"
"sale/internal/models"
"sale/internal/schemas"
"sale/internal/utils"
"github.com/gin-gonic/gin"
)
type SystemHandler struct{}
func NewSystemHandler() *SystemHandler {
return &SystemHandler{}
}
func (h *SystemHandler) GetSettings(c *gin.Context) {
var settings []models.SystemSetting
utils.DB.Find(&settings)
result := make(map[string]string)
for _, s := range settings {
result[s.Key] = s.Value
}
c.JSON(http.StatusOK, gin.H{"data": result})
}
func (h *SystemHandler) GetPublicSettings(c *gin.Context) {
publicKeys := []string{
"payment_channel_fee_rate",
"shipping_fee_first_weight",
"shipping_fee_per_gram",
"service_fee_rate",
"packaging_fee",
"international_fee_rate",
"enabled_payments",
}
var settings []models.SystemSetting
utils.DB.Where("`key` IN ?", publicKeys).Find(&settings)
result := make(map[string]string)
for _, s := range settings {
result[s.Key] = s.Value
}
c.JSON(http.StatusOK, gin.H{"data": result})
}
func (h *SystemHandler) GetStats(c *gin.Context) {
var userCount, productCount, orderCount int64
var totalRevenue float64
utils.DB.Model(&models.User{}).Count(&userCount)
utils.DB.Model(&models.Product{}).Count(&productCount)
utils.DB.Model(&models.Order{}).Count(&orderCount)
utils.DB.Model(&models.Order{}).Where("status = ?", "completed").Select("COALESCE(SUM(total_amount), 0)").Scan(&totalRevenue)
c.JSON(http.StatusOK, gin.H{
"data": gin.H{
"users": userCount,
"products": productCount,
"orders": orderCount,
"revenue": totalRevenue,
},
})
}
func (h *SystemHandler) UpdateSettings(c *gin.Context) {
var req schemas.UpdateSettingsRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
for key, value := range req.Settings {
var strValue string
switch v := value.(type) {
case string:
strValue = v
case float64:
strValue = fmt.Sprintf("%v", v)
case int:
strValue = fmt.Sprintf("%d", v)
case bool:
strValue = fmt.Sprintf("%v", v)
default:
strValue = fmt.Sprintf("%v", v)
}
var setting models.SystemSetting
result := utils.DB.Where("`key` = ?", key).First(&setting)
if result.Error != nil {
utils.DB.Create(&models.SystemSetting{Key: key, Value: strValue})
} else {
utils.DB.Model(&setting).Update("value", strValue)
}
}
c.JSON(http.StatusOK, gin.H{"message": "Settings updated successfully"})
}
func (h *SystemHandler) UpdateSMTP(c *gin.Context) {
var req map[string]string
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
smtpKeys := []string{"smtp_host", "smtp_port", "smtp_user", "smtp_password", "smtp_from"}
for _, key := range smtpKeys {
if value, ok := req[key]; ok {
var setting models.SystemSetting
result := utils.DB.Where("`key` = ?", key).First(&setting)
if result.Error != nil {
utils.DB.Create(&models.SystemSetting{Key: key, Value: value})
} else {
utils.DB.Model(&setting).Update("value", value)
}
}
}
c.JSON(http.StatusOK, gin.H{"message": "SMTP settings updated successfully"})
}
func (h *SystemHandler) UpdatePayment(c *gin.Context) {
var req map[string]string
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
for key, value := range req {
var setting models.SystemSetting
result := utils.DB.Where("`key` = ?", key).First(&setting)
if result.Error != nil {
utils.DB.Create(&models.SystemSetting{Key: key, Value: value})
} else {
utils.DB.Model(&setting).Update("value", value)
}
}
c.JSON(http.StatusOK, gin.H{"message": "Payment settings updated successfully"})
}
type SupplierHandler struct{}
func NewSupplierHandler() *SupplierHandler {
return &SupplierHandler{}
}
func (h *SupplierHandler) List(c *gin.Context) {
var suppliers []models.User
utils.DB.Where("role = ?", "supplier").Find(&suppliers)
c.JSON(http.StatusOK, gin.H{"data": suppliers})
}
func (h *SupplierHandler) Create(c *gin.Context) {
var req schemas.AddSupplierRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
hashedPassword, _ := utils.HashPassword(req.Password)
supplier := models.User{
Username: req.Username,
Email: req.Email,
PasswordHash: hashedPassword,
Role: "supplier",
InviteCode: utils.GenerateInviteCode(),
IsActive: true,
}
utils.DB.Create(&supplier)
c.JSON(http.StatusCreated, gin.H{"data": supplier})
}
func (h *SupplierHandler) Update(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
var supplier models.User
if err := utils.DB.Where("id = ? AND role = ?", id, "supplier").First(&supplier).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Supplier not found"})
return
}
var req struct {
Username *string `json:"username"`
Email *string `json:"email"`
IsActive *bool `json:"is_active"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
updates := make(map[string]interface{})
if req.Username != nil {
updates["username"] = *req.Username
}
if req.Email != nil {
updates["email"] = *req.Email
}
if req.IsActive != nil {
updates["is_active"] = *req.IsActive
}
utils.DB.Model(&supplier).Updates(updates)
utils.DB.Where("id = ?", id).First(&supplier)
c.JSON(http.StatusOK, gin.H{"data": supplier})
}
func (h *SupplierHandler) Delete(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
utils.DB.Where("id = ? AND role = ?", id, "supplier").Delete(&models.User{})
c.JSON(http.StatusOK, gin.H{"message": "Supplier deleted successfully"})
}
func (h *SupplierHandler) Authorize(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
var req schemas.AuthorizeSupplierRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
auth := models.SupplierAuthorization{
SupplierID: uint(id),
Type: req.Type,
RefID: req.RefID,
}
utils.DB.Create(&auth)
c.JSON(http.StatusCreated, gin.H{"data": auth})
}
type InventoryHandler struct{}
func NewInventoryHandler() *InventoryHandler {
return &InventoryHandler{}
}
func (h *InventoryHandler) SupplierList(c *gin.Context) {
userID := c.GetUint("user_id")
var inventory []models.Inventory
utils.DB.Where("supplier_id = ?", userID).Preload("Product").Find(&inventory)
c.JSON(http.StatusOK, gin.H{"data": inventory})
}
func (h *InventoryHandler) Update(c *gin.Context) {
userID := c.GetUint("user_id")
id, _ := strconv.Atoi(c.Param("id"))
var inventory models.Inventory
if err := utils.DB.Where("id = ? AND supplier_id = ?", id, userID).First(&inventory).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Inventory not found"})
return
}
var req schemas.UpdateInventoryRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
utils.DB.Model(&inventory).Update("quantity", req.Quantity)
c.JSON(http.StatusOK, gin.H{"data": inventory})
}
func (h *InventoryHandler) AdminList(c *gin.Context) {
var inventory []models.Inventory
utils.DB.Preload("Product").Find(&inventory)
c.JSON(http.StatusOK, gin.H{"data": inventory})
}