diff --git a/.gitignore b/.gitignore index 379de44..9c88b0b 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ log # Go workspace file go.work +.kiro diff --git a/api/v1/app/enter.go b/api/v1/app/enter.go index 9462bb1..c6ea4e3 100644 --- a/api/v1/app/enter.go +++ b/api/v1/app/enter.go @@ -8,6 +8,7 @@ type ApiGroup struct { OrderApi TeacherVip RedeemCodeApi + WithApi } var userService = service.ServiceGroupApp.UserServiceGroup.UserService @@ -16,3 +17,4 @@ var bannerService = service.ServiceGroupApp.AppServiceGroup.BannerService var orderService = service.ServiceGroupApp.AppServiceGroup.OrderService var teacherVipService = service.ServiceGroupApp.AppServiceGroup.TeacherVipService var redeemCodeService = service.ServiceGroupApp.AppServiceGroup.RedeemCodeService +var withService = service.ServiceGroupApp.AppServiceGroup.WithService diff --git a/api/v1/app/with.go b/api/v1/app/with.go new file mode 100644 index 0000000..84f580b --- /dev/null +++ b/api/v1/app/with.go @@ -0,0 +1,142 @@ +package app + +import ( + "git.echol.cn/loser/lckt/global" + "git.echol.cn/loser/lckt/model/app" + "git.echol.cn/loser/lckt/model/app/request" + r "git.echol.cn/loser/lckt/model/common/response" + "git.echol.cn/loser/lckt/utils" + "github.com/gin-gonic/gin" + "go.uber.org/zap" +) + +// WithApi 提现接口 +type WithApi struct{} + +// Create 创建提现请求 +func (w *WithApi) Create(c *gin.Context) { + var p app.With + if err := c.ShouldBind(&p); err != nil { + r.FailWithMessage("申请提现参数有误:", c) + global.GVA_LOG.Error("申请提现参数有误:", zap.Error(err)) + return + } + + userId := utils.GetUserID(c) + p.UserID = userId + p.Status = 1 // 设置状态为待处理 + + err := withService.Create(p) + if err != nil { + r.FailWithMessage("创建提现请求失败", c) + return + } + + r.OkWithMessage("申请提现请求成功", c) +} + +// GetList 获取提现列表 +func (w *WithApi) GetList(c *gin.Context) { + var p request.GetWithList + if err := c.ShouldBind(&p); err != nil { + r.FailWithMessage("获取提现列表参数有误:", c) + global.GVA_LOG.Error("获取提现列表参数有误:", zap.Error(err)) + return + } + + userId := utils.GetUserID(c) + p.UserId = userId + + list, total, err := withService.GetList(p) + if err != nil { + r.FailWithMessage("获取提现列表失败", c) + return + } + + r.OkWithDetailed(r.PageResult{ + List: list, + Total: total, + Page: p.Page, + PageSize: p.PageSize, + }, "获取提现列表成功", c) +} + +// Cancel 取消提现请求 +func (w *WithApi) Cancel(c *gin.Context) { + var p app.With + if err := c.ShouldBind(&p); err != nil { + r.FailWithMessage("取消提现请求参数有误:", c) + global.GVA_LOG.Error("取消提现请求参数有误:", zap.Error(err)) + return + } + + userId := utils.GetUserID(c) + p.UserID = userId + + if p.ID == 0 { + r.FailWithMessage("提现ID不能为空", c) + return + } + + p.Status = 4 // 设置状态为取消 + + err := withService.UpdateStatus(p) + if err != nil { + r.FailWithMessage("取消提现请求失败", c) + return + } + + r.OkWithMessage("取消提现请求成功", c) +} + +// =============管理后台接口================= + +// GetAdminList 获取提现列表(管理员) +func (w *WithApi) GetAdminList(c *gin.Context) { + var p request.GetWithList + if err := c.ShouldBind(&p); err != nil { + r.FailWithMessage("获取提现列表参数有误:", c) + global.GVA_LOG.Error("获取提现列表参数有误:", zap.Error(err)) + return + } + + list, total, err := withService.GetList(p) + if err != nil { + r.FailWithMessage("获取提现列表失败", c) + return + } + + r.OkWithDetailed(r.PageResult{ + List: list, + Total: total, + Page: p.Page, + PageSize: p.PageSize, + }, "获取提现列表成功", c) +} + +// UpdateStatus 更新提现状态(管理员) +func (w *WithApi) UpdateStatus(c *gin.Context) { + var p app.With + if err := c.ShouldBind(&p); err != nil { + r.FailWithMessage("更新提现状态参数有误:", c) + global.GVA_LOG.Error("更新提现状态参数有误:", zap.Error(err)) + return + } + + if p.ID == 0 { + r.FailWithMessage("提现ID不能为空", c) + return + } + if p.Status == 0 { + r.FailWithMessage("提现状态不能为空", c) + return + } + + err := withService.UpdateStatus(p) + if err != nil { + r.FailWithMessage("更新提现状态失败", c) + return + } + + r.OkWithMessage("更新提现状态成功", c) +} diff --git a/initialize/router.go b/initialize/router.go index 6757c5f..5f3b069 100644 --- a/initialize/router.go +++ b/initialize/router.go @@ -118,6 +118,7 @@ func Routers() *gin.Engine { appRouter.InitBannerRouter(PrivateGroup, PublicGroup) // Banner相关路由 appRouter.InitOrderRouter(AppAuthGroup, PrivateGroup, PublicGroup) // 订单相关路由 appRouter.InitRedeemCodeRouter(AppAuthGroup, PrivateGroup) // 兑换码相关路由 + appRouter.InitWithRouter(AppAuthGroup, PrivateGroup) } //插件路由安装 diff --git a/model/app/request/with.go b/model/app/request/with.go new file mode 100644 index 0000000..2c84d11 --- /dev/null +++ b/model/app/request/with.go @@ -0,0 +1,12 @@ +package request + +import common "git.echol.cn/loser/lckt/model/common/request" + +type GetWithList struct { + common.PageInfo + UserId uint `json:"user_id" form:"user_id"` // 用户ID + UserName string `json:"user_name" form:"user_name"` // 用户名 + Status int `json:"status" form:"status"` + StartTime string `json:"start_time" form:"start_time"` + EndTime string `json:"end_time" form:"end_time"` +} diff --git a/model/app/with.go b/model/app/with.go new file mode 100644 index 0000000..b35f3e1 --- /dev/null +++ b/model/app/with.go @@ -0,0 +1,23 @@ +package app + +import "git.echol.cn/loser/lckt/global" + +// With 提现管理 +type With struct { + global.GVA_MODEL + WithType int `json:"withType" form:"withType" gorm:"comment:提现类型 1 微信 2 支付宝 3 银行卡"` + UserID uint `json:"userId" form:"userId" gorm:"comment:用户ID"` + UserName string `json:"userName" form:"userName" gorm:"comment:用户名称"` + Amount float64 `json:"amount" form:"amount" gorm:"comment:提现金额"` + RealAmount float64 `json:"realAmount" form:"realAmount" gorm:"comment:实际到账金额"` + Status int `json:"status" form:"status" gorm:"comment:状态 1 待处理 2 已完成 3 已拒绝 4 已取消"` + // 到账时间 + ArriveTime string `json:"arriveTime" form:"arriveTime" gorm:"comment:到账时间"` + // 账户信息 + AccountInfo string `json:"accountInfo" form:"accountInfo" gorm:"type:text;comment:账户信息 收款码或银行卡等"` + Remark string `json:"remark" form:"remark" gorm:"type:text;comment:备注"` +} + +func (With) TableName() string { + return "app_with" +} diff --git a/router/app/enter.go b/router/app/enter.go index f1e6b5d..1f57485 100644 --- a/router/app/enter.go +++ b/router/app/enter.go @@ -7,6 +7,7 @@ type RouterGroup struct { BannerRouter OrderRouter RedeemCodeRouter + WithRouter } var userApi = api.ApiGroupApp.AppApiGroup.AppUserApi @@ -14,3 +15,4 @@ var bannerApi = api.ApiGroupApp.AppApiGroup.BannerApi var orderApi = api.ApiGroupApp.AppApiGroup.OrderApi var teacherVipApi = api.ApiGroupApp.AppApiGroup.TeacherVip var redeemCodeApi = api.ApiGroupApp.AppApiGroup.RedeemCodeApi +var withApi = api.ApiGroupApp.AppApiGroup.WithApi diff --git a/router/app/with.go b/router/app/with.go new file mode 100644 index 0000000..293ca8c --- /dev/null +++ b/router/app/with.go @@ -0,0 +1,21 @@ +package app + +import "github.com/gin-gonic/gin" + +type WithRouter struct{} + +// InitWithRouter 初始化 With 路由信息 +func (s *WithRouter) InitWithRouter(AppRouter, SysteamRouter *gin.RouterGroup) { + appRouter := AppRouter.Group("with") + sysRouter := SysteamRouter.Group("sys/with") + + { + appRouter.POST("", withApi.Create) // 创建提现请求 + appRouter.GET("list", withApi.GetList) // 获取提现列表 + appRouter.PUT("cancel", withApi.Cancel) // 取消提现请求 + } + { + sysRouter.GET("list", withApi.GetAdminList) // 获取提现列表 + sysRouter.PUT("", withApi.UpdateStatus) // 更新提现状态 + } +} diff --git a/service/app/enter.go b/service/app/enter.go index 2ed9d99..3a3f172 100644 --- a/service/app/enter.go +++ b/service/app/enter.go @@ -6,4 +6,5 @@ type ServiceGroup struct { OrderService TeacherVipService RedeemCodeService + WithService } diff --git a/service/app/with.go b/service/app/with.go new file mode 100644 index 0000000..0af4462 --- /dev/null +++ b/service/app/with.go @@ -0,0 +1,164 @@ +package app + +import ( + "git.echol.cn/loser/lckt/global" + "git.echol.cn/loser/lckt/model/app" + "git.echol.cn/loser/lckt/model/app/request" + "git.echol.cn/loser/lckt/model/user" + "go.uber.org/zap" + "gorm.io/gorm" + "time" +) + +// WithService 提现服务 +type WithService struct{} + +func (s WithService) Create(p app.With) (err error) { + err = global.GVA_DB.Create(&p).Error + if err != nil { + global.GVA_LOG.Error("创建提现请求失败", zap.Error(err)) + return + } + + // 扣除用户余额 + err = global.GVA_DB.Model(&user.User{}).Where("id = ?", p.UserID).Update("balance", gorm.Expr("balance - ?", p.Amount)).Error + if err != nil { + global.GVA_LOG.Error("扣除用户余额失败", zap.Error(err)) + return + } + + return +} + +func (s WithService) GetList(p request.GetWithList) (list []app.With, total int64, err error) { + limit := p.PageSize + offset := p.PageSize * (p.Page - 1) + db := global.GVA_DB.Model(&app.With{}) + + if p.UserId != 0 { + db = db.Where("user_id = ?", p.UserId) + } + if p.UserName != "" { + db = db.Joins("JOIN app_user ON app_user.id = app_with.user_id").Where("app_user.user_name LIKE ?", "%"+p.UserName+"%") + } + if p.Status != 0 { + db = db.Where("status = ?", p.Status) + } + if p.StartTime != "" { + db = db.Where("created_at >= ?", p.StartTime) + } + if p.EndTime != "" { + db = db.Where("created_at <= ?", p.EndTime) + } + + err = db.Count(&total).Error + if err != nil { + global.GVA_LOG.Error("获取提现列表总数失败", zap.Error(err)) + return + } + + err = db.Limit(limit).Offset(offset).Order("created_at DESC").Find(&list).Error + if err != nil { + global.GVA_LOG.Error("获取提现列表失败", zap.Error(err)) + return + } + return +} + +func (s WithService) UpdateStatus(p app.With) (err error) { + var userInfo user.User + err = global.GVA_DB.Model(&user.User{}).Where("id = ?", p.UserID).First(&userInfo).Error + if err != nil { + global.GVA_LOG.Error("查询用户信息失败", zap.Error(err)) + return + } + + if p.Status == 2 { + // 通过申请 + var with app.With + err = global.GVA_DB.Model(&app.With{}).Where("id = ?", p.ID).First(&with).Error + if err != nil { + global.GVA_LOG.Error("查询提现请求失败", zap.Error(err)) + return + } + if with.Status != 1 { + global.GVA_LOG.Error("提现请求状态错误,无法通过", zap.Error(err)) + return + } + + with.Status = 2 + with.ArriveTime = time.Now().Format("2006-01-02 15:04:05") + with.RealAmount = p.RealAmount + err = global.GVA_DB.Save(&with).Error + if err != nil { + global.GVA_LOG.Error("更新提现请求状态失败", zap.Error(err)) + return + } + + // 增加余额变更记录 + var record app.BalanceLog + record.UserID = with.UserID + record.ChangeType = 2 // 提现 + record.ChangeValue = with.Amount + record.Balance = userInfo.Balance + + err = global.GVA_DB.Create(&record).Error + if err != nil { + global.GVA_LOG.Error("创建余额变更记录失败", zap.Error(err)) + return + } + return + } + if p.Status == 3 { + // 拒绝申请,退还金额 + var with app.With + err = global.GVA_DB.Model(&app.With{}).Where("id = ?", p.ID).First(&with).Error + if err != nil { + global.GVA_LOG.Error("查询提现请求失败", zap.Error(err)) + return + } + if with.Status != 1 { + global.GVA_LOG.Error("提现请求状态错误,无法拒绝", zap.Error(err)) + return + } + with.Status = 3 + with.Remark = p.Remark + // 退还金额 + err = global.GVA_DB.Model(&user.User{}).Where("id = ?", with.UserID).Update("balance", gorm.Expr("balance + ?", with.Amount)).Error + if err != nil { + global.GVA_LOG.Error("退还用户余额失败", zap.Error(err)) + return + } + err = global.GVA_DB.Save(&with).Error + if err != nil { + global.GVA_LOG.Error("更新提现请求状态失败", zap.Error(err)) + return + } + } + if p.Status == 4 { + // 用户取消申请,退还金额 + var with app.With + err = global.GVA_DB.Model(&app.With{}).Where("id = ?", p.ID).First(&with).Error + if err != nil { + global.GVA_LOG.Error("查询提现请求失败", zap.Error(err)) + return + } + if with.Status != 1 { + global.GVA_LOG.Error("提现请求状态错误,无法取消", zap.Error(err)) + return + } + with.Status = 4 + // 退还金额 + err = global.GVA_DB.Model(&user.User{}).Where("id = ?", with.UserID).Update("balance", gorm.Expr("balance + ?", with.Amount)).Error + if err != nil { + global.GVA_LOG.Error("退还用户余额失败", zap.Error(err)) + return + } + err = global.GVA_DB.Save(&with).Error + if err != nil { + global.GVA_LOG.Error("更新提现请求状态失败", zap.Error(err)) + return + } + } + return +}