This commit is contained in:
2026-01-30 16:51:19 +08:00
commit 4609219a4d
606 changed files with 65580 additions and 0 deletions

View File

@@ -0,0 +1,149 @@
package admin_agent
import (
"context"
"errors"
"fmt"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"tyass-server/app/main/model"
"tyass-server/common/xerr"
"github.com/Masterminds/squirrel"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
type AdminBatchUnfreezeAgentCommissionLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminBatchUnfreezeAgentCommissionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminBatchUnfreezeAgentCommissionLogic {
return &AdminBatchUnfreezeAgentCommissionLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminBatchUnfreezeAgentCommissionLogic) AdminBatchUnfreezeAgentCommission(req *types.AdminBatchUnfreezeAgentCommissionReq) (resp *types.AdminBatchUnfreezeAgentCommissionResp, err error) {
// 构建查询条件状态为1冻结中
builder := l.svcCtx.AgentCommissionModel.SelectBuilder().Where(squirrel.Eq{"status": 1})
// 如果指定了代理商ID则只查询该代理商的冻结佣金
if req.AgentId != nil && *req.AgentId > 0 {
builder = builder.Where(squirrel.Eq{"agent_id": *req.AgentId})
}
// 查询所有冻结中的佣金记录
commissions, err := l.svcCtx.AgentCommissionModel.FindAll(l.ctx, builder, "")
if err != nil {
return nil, err
}
// 如果没有冻结的佣金,直接返回
if len(commissions) == 0 {
resp = &types.AdminBatchUnfreezeAgentCommissionResp{
Success: true,
Count: 0,
Amount: 0,
}
return
}
// 计算总金额
var totalAmount float64
for _, commission := range commissions {
totalAmount += commission.Amount
}
// 开始事务
err = l.svcCtx.AgentCommissionModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
// 按代理商分组更新钱包余额
agentWalletMap := make(map[int64]*model.AgentWallet)
// 遍历所有冻结的佣金,更新状态
for _, commission := range commissions {
// 更新佣金状态为已结算
commission.Status = 0
err := l.svcCtx.AgentCommissionModel.UpdateWithVersion(ctx, session, commission)
if err != nil {
// 如果是版本冲突错误,重新查询最新的数据后重试
if errors.Is(err, model.ErrNoRowsUpdate) {
latestCommission, findErr := l.svcCtx.AgentCommissionModel.FindOne(ctx, commission.Id)
if findErr != nil {
return findErr
}
// 检查状态是否已被其他操作修改
if latestCommission.Status != 1 {
return xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, fmt.Sprintf("佣金 %d 的状态已被其他操作修改,当前状态: %d", commission.Id, latestCommission.Status))
}
// 重新更新状态
latestCommission.Status = 0
updateErr := l.svcCtx.AgentCommissionModel.UpdateWithVersion(ctx, session, latestCommission)
if updateErr != nil {
return updateErr
}
// 更新引用,使用最新的数据
commission.Version = latestCommission.Version
} else {
return err
}
}
// 累加到对应代理商的钱包数据
if wallet, exists := agentWalletMap[commission.AgentId]; exists {
wallet.Balance += commission.Amount
wallet.FrozenBalance -= commission.Amount
} else {
// 查询该代理商的钱包
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(ctx, commission.AgentId)
if err != nil {
return err
}
wallet.Balance += commission.Amount
wallet.FrozenBalance -= commission.Amount
agentWalletMap[commission.AgentId] = wallet
}
}
// 更新所有受影响代理商的钱包
for _, wallet := range agentWalletMap {
err := l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, wallet)
if err != nil {
// 如果是版本冲突错误,重新查询最新的数据后重试
if errors.Is(err, model.ErrNoRowsUpdate) {
latestWallet, findErr := l.svcCtx.AgentWalletModel.FindOneByAgentId(ctx, wallet.AgentId)
if findErr != nil {
return findErr
}
// 重新累加金额
latestWallet.Balance = wallet.Balance
latestWallet.FrozenBalance = wallet.FrozenBalance
updateErr := l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, latestWallet)
if updateErr != nil {
return updateErr
}
} else {
return err
}
}
}
return nil
})
if err != nil {
return nil, xerr.NewErrMsg("批量解冻失败: " + err.Error())
}
resp = &types.AdminBatchUnfreezeAgentCommissionResp{
Success: true,
Count: int64(len(commissions)),
Amount: totalAmount,
}
return
}

View File

@@ -0,0 +1,84 @@
package admin_agent
import (
"context"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/Masterminds/squirrel"
"github.com/jinzhu/copier"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetAgentCommissionDeductionListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetAgentCommissionDeductionListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetAgentCommissionDeductionListLogic {
return &AdminGetAgentCommissionDeductionListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetAgentCommissionDeductionListLogic) AdminGetAgentCommissionDeductionList(req *types.AdminGetAgentCommissionDeductionListReq) (resp *types.AdminGetAgentCommissionDeductionListResp, err error) {
builder := l.svcCtx.AgentCommissionDeductionModel.SelectBuilder()
if req.AgentId != nil {
builder = builder.Where(squirrel.Eq{"agent_id": *req.AgentId})
}
if req.Type != nil && *req.Type != "" {
builder = builder.Where(squirrel.Eq{"type": *req.Type})
}
if req.Status != nil {
builder = builder.Where(squirrel.Eq{"status": *req.Status})
}
// 产品名筛选需先查product_id
if req.ProductName != nil && *req.ProductName != "" {
products, err := l.svcCtx.ProductModel.FindAll(l.ctx, l.svcCtx.ProductModel.SelectBuilder().Where(squirrel.Eq{"product_name": *req.ProductName}), "")
if err != nil || len(products) == 0 {
return &types.AdminGetAgentCommissionDeductionListResp{Total: 0, Items: []types.AgentCommissionDeductionListItem{}}, nil
}
builder = builder.Where("product_id = ?", products[0].Id)
}
list, total, err := l.svcCtx.AgentCommissionDeductionModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
if err != nil {
return nil, err
}
// 批量查product_id->name
productIds := make(map[int64]struct{})
for _, v := range list {
productIds[v.ProductId] = struct{}{}
}
productIdArr := make([]int64, 0, len(productIds))
for id := range productIds {
productIdArr = append(productIdArr, id)
}
productNameMap := make(map[int64]string)
if len(productIdArr) > 0 {
build := l.svcCtx.ProductModel.SelectBuilder().Where(squirrel.Eq{"id": productIdArr})
products, _ := l.svcCtx.ProductModel.FindAll(l.ctx, build, "")
for _, p := range products {
productNameMap[p.Id] = p.ProductName
}
}
items := make([]types.AgentCommissionDeductionListItem, 0, len(list))
for _, v := range list {
item := types.AgentCommissionDeductionListItem{}
_ = copier.Copy(&item, v)
item.ProductName = productNameMap[v.ProductId]
item.CreateTime = v.CreateTime.Format("2006-01-02 15:04:05")
items = append(items, item)
}
resp = &types.AdminGetAgentCommissionDeductionListResp{
Total: total,
Items: items,
}
return
}

View File

@@ -0,0 +1,105 @@
package admin_agent
import (
"context"
"time"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/Masterminds/squirrel"
"github.com/jinzhu/copier"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetAgentCommissionListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetAgentCommissionListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetAgentCommissionListLogic {
return &AdminGetAgentCommissionListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetAgentCommissionListLogic) AdminGetAgentCommissionList(req *types.AdminGetAgentCommissionListReq) (resp *types.AdminGetAgentCommissionListResp, err error) {
builder := l.svcCtx.AgentCommissionModel.SelectBuilder()
if req.AgentId != nil {
builder = builder.Where(squirrel.Eq{"agent_id": *req.AgentId})
}
if req.OrderId != nil {
builder = builder.Where(squirrel.Eq{"order_id": *req.OrderId})
}
if req.Status != nil {
builder = builder.Where(squirrel.Eq{"status": *req.Status})
}
// 时间范围筛选
if req.CreateTimeStart != nil && *req.CreateTimeStart != "" {
startTime, err := time.Parse("2006-01-02 15:04:05", *req.CreateTimeStart)
if err == nil {
builder = builder.Where(squirrel.GtOrEq{"create_time": startTime})
}
}
if req.CreateTimeEnd != nil && *req.CreateTimeEnd != "" {
endTime, err := time.Parse("2006-01-02 15:04:05", *req.CreateTimeEnd)
if err == nil {
builder = builder.Where(squirrel.LtOrEq{"create_time": endTime})
}
}
// 先查出所有product_id对应的product_name如有product_name筛选需反查id
if req.ProductName != nil && *req.ProductName != "" {
// 支持模糊匹配产品名称
products, err := l.svcCtx.ProductModel.FindAll(l.ctx, l.svcCtx.ProductModel.SelectBuilder().Where(squirrel.Like{"product_name": "%" + *req.ProductName + "%"}), "")
if err != nil || len(products) == 0 {
return &types.AdminGetAgentCommissionListResp{Total: 0, Items: []types.AgentCommissionListItem{}}, nil
}
productIds := make([]int64, 0, len(products))
for _, p := range products {
productIds = append(productIds, p.Id)
}
builder = builder.Where(squirrel.Eq{"product_id": productIds})
}
list, total, err := l.svcCtx.AgentCommissionModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
if err != nil {
return nil, err
}
// 批量查product_name
productIds := make(map[int64]struct{})
for _, v := range list {
productIds[v.ProductId] = struct{}{}
}
productNameMap := make(map[int64]string)
if len(productIds) > 0 {
ids := make([]int64, 0, len(productIds))
for id := range productIds {
ids = append(ids, id)
}
builder := l.svcCtx.ProductModel.SelectBuilder().Where(squirrel.Eq{"id": ids})
products, _ := l.svcCtx.ProductModel.FindAll(l.ctx, builder, "")
for _, p := range products {
productNameMap[p.Id] = p.ProductName
}
}
items := make([]types.AgentCommissionListItem, 0, len(list))
for _, v := range list {
item := types.AgentCommissionListItem{}
_ = copier.Copy(&item, v)
item.ProductName = productNameMap[v.ProductId]
item.CreateTime = v.CreateTime.Format("2006-01-02 15:04:05")
items = append(items, item)
}
resp = &types.AdminGetAgentCommissionListResp{
Total: total,
Items: items,
}
return
}

View File

@@ -0,0 +1,86 @@
package admin_agent
import (
"context"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/Masterminds/squirrel"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetAgentLinkListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetAgentLinkListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetAgentLinkListLogic {
return &AdminGetAgentLinkListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetAgentLinkListLogic) AdminGetAgentLinkList(req *types.AdminGetAgentLinkListReq) (resp *types.AdminGetAgentLinkListResp, err error) {
builder := l.svcCtx.AgentLinkModel.SelectBuilder()
if req.AgentId != nil {
builder = builder.Where("agent_id = ?", *req.AgentId)
}
if req.LinkIdentifier != nil && *req.LinkIdentifier != "" {
builder = builder.Where("link_identifier = ?", *req.LinkIdentifier)
}
// 先查出所有product_id对应的product_name如有product_name筛选需反查id
var productIdFilter int64
if req.ProductName != nil && *req.ProductName != "" {
// 只支持精确匹配,如需模糊可扩展
products, err := l.svcCtx.ProductModel.FindAll(l.ctx, l.svcCtx.ProductModel.SelectBuilder().Where(squirrel.Eq{"product_name": *req.ProductName}), "")
if err != nil || len(products) == 0 {
return &types.AdminGetAgentLinkListResp{Total: 0, Items: []types.AgentLinkListItem{}}, nil
}
productIdFilter = products[0].Id
builder = builder.Where("product_id = ?", productIdFilter)
}
links, total, err := l.svcCtx.AgentLinkModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "id DESC")
if err != nil {
return nil, err
}
// 批量查product_id->name避免N+1
productIdSet := make(map[int64]struct{})
for _, link := range links {
productIdSet[link.ProductId] = struct{}{}
}
productIdList := make([]int64, 0, len(productIdSet))
for id := range productIdSet {
productIdList = append(productIdList, id)
}
productNameMap := make(map[int64]string)
if len(productIdList) > 0 {
products, _ := l.svcCtx.ProductModel.FindAll(l.ctx, l.svcCtx.ProductModel.SelectBuilder().Where(squirrel.Eq{"id": productIdList}), "")
for _, p := range products {
productNameMap[p.Id] = p.ProductName
}
}
items := make([]types.AgentLinkListItem, 0, len(links))
for _, link := range links {
items = append(items, types.AgentLinkListItem{
AgentId: link.AgentId,
ProductName: productNameMap[link.ProductId],
Price: link.Price,
LinkIdentifier: link.LinkIdentifier,
CreateTime: link.CreateTime.Format("2006-01-02 15:04:05"),
})
}
resp = &types.AdminGetAgentLinkListResp{
Total: total,
Items: items,
}
return
}

View File

@@ -0,0 +1,100 @@
package admin_agent
import (
"context"
"fmt"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/Masterminds/squirrel"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetAgentLinkProductStatisticsLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetAgentLinkProductStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetAgentLinkProductStatisticsLogic {
return &AdminGetAgentLinkProductStatisticsLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetAgentLinkProductStatisticsLogic) AdminGetAgentLinkProductStatistics(req *types.AdminGetAgentLinkProductStatisticsReq) (resp *types.AdminGetAgentLinkProductStatisticsResp, err error) {
// 构建查询
query := squirrel.Select(
"p.product_name",
"COUNT(al.id) as link_count",
).
From("agent_link al").
Join("product p ON al.product_id = p.id").
Where(squirrel.Eq{"al.del_state": 0}).
Where(squirrel.Eq{"p.del_state": 0}).
GroupBy("p.product_name").
OrderBy("link_count DESC")
// 执行查询
sql, args, err := query.ToSql()
if err != nil {
return nil, err
}
type Result struct {
ProductName string `db:"product_name"`
LinkCount int64 `db:"link_count"`
}
var results []Result
// 使用模型的方法执行查询
// 通过反射获取底层的QueryRowsNoCacheCtx方法避免直接类型断言
if agentLinkModel, ok := l.svcCtx.AgentLinkModel.(interface {
QueryRowsNoCacheCtx(ctx context.Context, v interface{}, query string, args ...interface{}) error
}); ok {
err = agentLinkModel.QueryRowsNoCacheCtx(l.ctx, &results, sql, args...)
} else {
// 如果无法使用模型的方法,则使用原始的连接方式(安全地获取连接)
if cachedConn, ok := l.svcCtx.AgentLinkModel.(interface {
GetConn() interface{}
}); ok {
conn := cachedConn.GetConn()
if sqlxConn, ok := conn.(interface {
QueryRowsCtx(ctx context.Context, v interface{}, query string, args ...interface{}) error
}); ok {
err = sqlxConn.QueryRowsCtx(l.ctx, &results, sql, args...)
} else {
return nil, fmt.Errorf("无法获取数据库连接")
}
} else {
return nil, fmt.Errorf("无法获取数据库连接")
}
}
if err != nil {
return nil, err
}
// 处理空结果
if len(results) == 0 {
return &types.AdminGetAgentLinkProductStatisticsResp{
Items: []types.AgentLinkProductStatisticsItem{},
}, nil
}
// 转换为返回结果
items := make([]types.AgentLinkProductStatisticsItem, 0, len(results))
for _, r := range results {
items = append(items, types.AgentLinkProductStatisticsItem{
ProductName: r.ProductName,
LinkCount: r.LinkCount,
})
}
return &types.AdminGetAgentLinkProductStatisticsResp{
Items: items,
}, nil
}

View File

@@ -0,0 +1,122 @@
package admin_agent
import (
"context"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"tyass-server/app/main/model"
"tyass-server/common/tool"
"tyass-server/common/xerr"
"tyass-server/pkg/lzkit/crypto"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetAgentListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetAgentListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetAgentListLogic {
return &AdminGetAgentListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetAgentListLogic) AdminGetAgentList(req *types.AdminGetAgentListReq) (resp *types.AdminGetAgentListResp, err error) {
builder := l.svcCtx.AgentModel.SelectBuilder()
if req.Mobile != nil && *req.Mobile != "" {
builder = builder.Where("mobile = ?", *req.Mobile)
}
if req.Region != nil && *req.Region != "" {
builder = builder.Where("region = ?", *req.Region)
}
// 新增如果传入ParentAgentId则查找其所有1级下级代理
if req.ParentAgentId != nil {
closureBuilder := l.svcCtx.AgentClosureModel.SelectBuilder().Where("ancestor_id = ? AND depth = 1", *req.ParentAgentId)
closures, cerr := l.svcCtx.AgentClosureModel.FindAll(l.ctx, closureBuilder, "")
if cerr != nil {
return nil, cerr
}
if len(closures) == 0 {
resp = &types.AdminGetAgentListResp{Total: 0, Items: []types.AgentListItem{}}
return resp, nil
}
ids := make([]int64, 0, len(closures))
for _, c := range closures {
ids = append(ids, c.DescendantId)
}
// 将int64切片转换为interface{}切片以便squirrel正确处理IN查询
interfaceIds := make([]interface{}, len(ids))
for i, id := range ids {
interfaceIds[i] = id
}
// 使用项目中的InPlaceholders函数生成正确数量的占位符
builder = builder.Where("id IN ("+tool.InPlaceholders(len(interfaceIds))+")", interfaceIds...)
}
agents, total, err := l.svcCtx.AgentModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "id DESC")
if err != nil {
return nil, err
}
items := make([]types.AgentListItem, 0, len(agents))
for _, agent := range agents {
item := types.AgentListItem{
Id: agent.Id,
UserId: agent.UserId,
LevelName: agent.LevelName,
Region: agent.Region,
CreateTime: agent.CreateTime.Format("2006-01-02 15:04:05"),
}
if req.ParentAgentId != nil {
item.ParentAgentId = *req.ParentAgentId
}
agent.Mobile, err = crypto.DecryptMobile(agent.Mobile, l.svcCtx.Config.Encrypt.SecretKey)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理信息, 解密手机号失败: %v", err)
}
item.Mobile = agent.Mobile
if agent.MembershipExpiryTime.Valid {
item.MembershipExpiryTime = agent.MembershipExpiryTime.Time.Format("2006-01-02 15:04:05")
}
// 查询钱包信息
wallet, _ := l.svcCtx.AgentWalletModel.FindOneByAgentId(l.ctx, agent.Id)
if wallet != nil {
item.Balance = wallet.Balance
item.TotalEarnings = wallet.TotalEarnings
item.FrozenBalance = wallet.FrozenBalance
item.WithdrawnAmount = wallet.WithdrawnAmount
}
// 查询实名认证信息
realNameInfo, _ := l.svcCtx.AgentRealNameModel.FindOneByAgentId(l.ctx, agent.Id)
if realNameInfo != nil {
item.IsRealNameVerified = realNameInfo.Status == model.AgentRealNameStatusApproved
item.RealName = realNameInfo.Name
item.IdCard = realNameInfo.IdCard
item.RealNameStatus = realNameInfo.Status
} else {
item.IsRealNameVerified = false
item.RealName = ""
item.IdCard = ""
item.RealNameStatus = ""
}
items = append(items, item)
}
resp = &types.AdminGetAgentListResp{
Total: total,
Items: items,
}
return
}

View File

@@ -0,0 +1,51 @@
package admin_agent
import (
"context"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/Masterminds/squirrel"
"github.com/jinzhu/copier"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetAgentMembershipConfigListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetAgentMembershipConfigListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetAgentMembershipConfigListLogic {
return &AdminGetAgentMembershipConfigListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetAgentMembershipConfigListLogic) AdminGetAgentMembershipConfigList(req *types.AdminGetAgentMembershipConfigListReq) (resp *types.AdminGetAgentMembershipConfigListResp, err error) {
builder := l.svcCtx.AgentMembershipConfigModel.SelectBuilder()
if req.LevelName != nil && *req.LevelName != "" {
builder = builder.Where(squirrel.Eq{"level_name": *req.LevelName})
}
list, total, err := l.svcCtx.AgentMembershipConfigModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "id DESC")
if err != nil {
return nil, err
}
items := make([]types.AgentMembershipConfigListItem, 0, len(list))
for _, v := range list {
var item types.AgentMembershipConfigListItem
if err := copier.Copy(&item, v); err != nil {
l.Logger.Errorf("copy error: %v", err)
continue
}
item.CreateTime = v.CreateTime.Format("2006-01-02 15:04:05")
items = append(items, item)
}
resp = &types.AdminGetAgentMembershipConfigListResp{
Total: total,
Items: items,
}
return
}

View File

@@ -0,0 +1,64 @@
package admin_agent
import (
"context"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/Masterminds/squirrel"
"github.com/jinzhu/copier"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetAgentMembershipRechargeOrderListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetAgentMembershipRechargeOrderListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetAgentMembershipRechargeOrderListLogic {
return &AdminGetAgentMembershipRechargeOrderListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetAgentMembershipRechargeOrderListLogic) AdminGetAgentMembershipRechargeOrderList(req *types.AdminGetAgentMembershipRechargeOrderListReq) (resp *types.AdminGetAgentMembershipRechargeOrderListResp, err error) {
builder := l.svcCtx.AgentMembershipRechargeOrderModel.SelectBuilder()
if req.UserId != nil {
builder = builder.Where(squirrel.Eq{"user_id": *req.UserId})
}
if req.AgentId != nil {
builder = builder.Where(squirrel.Eq{"agent_id": *req.AgentId})
}
if req.OrderNo != nil && *req.OrderNo != "" {
builder = builder.Where(squirrel.Eq{"order_no": *req.OrderNo})
}
if req.PlatformOrderId != nil && *req.PlatformOrderId != "" {
builder = builder.Where(squirrel.Eq{"platform_order_id": *req.PlatformOrderId})
}
if req.Status != nil && *req.Status != "" {
builder = builder.Where(squirrel.Eq{"status": *req.Status})
}
if req.PaymentMethod != nil && *req.PaymentMethod != "" {
builder = builder.Where(squirrel.Eq{"payment_method": *req.PaymentMethod})
}
list, total, err := l.svcCtx.AgentMembershipRechargeOrderModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
if err != nil {
return nil, err
}
items := make([]types.AgentMembershipRechargeOrderListItem, 0, len(list))
for _, v := range list {
item := types.AgentMembershipRechargeOrderListItem{}
_ = copier.Copy(&item, v)
item.CreateTime = v.CreateTime.Format("2006-01-02 15:04:05")
items = append(items, item)
}
resp = &types.AdminGetAgentMembershipRechargeOrderListResp{
Total: total,
Items: items,
}
return
}

View File

@@ -0,0 +1,60 @@
package admin_agent
import (
"context"
"fmt"
"time"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetAgentOrderStatisticsLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetAgentOrderStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetAgentOrderStatisticsLogic {
return &AdminGetAgentOrderStatisticsLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetAgentOrderStatisticsLogic) AdminGetAgentOrderStatistics(req *types.AdminGetAgentOrderStatisticsReq) (resp *types.AdminGetAgentOrderStatisticsResp, err error) {
// 获取今日的开始和结束时间
today := time.Now()
startOfDay := time.Date(today.Year(), today.Month(), today.Day(), 0, 0, 0, 0, today.Location())
endOfDay := startOfDay.Add(24 * time.Hour)
// 构建查询条件
builder := l.svcCtx.AgentOrderModel.SelectBuilder()
// 查询总代理订单数
totalBuilder := builder
totalAgentOrderCount, err := l.svcCtx.AgentOrderModel.FindCount(l.ctx, totalBuilder, "id")
if err != nil {
logx.Errorf("查询总代理订单数失败: %v", err)
return nil, fmt.Errorf("查询总代理订单数失败: %w", err)
}
// 查询今日代理订单数
todayBuilder := builder.Where("create_time >= ? AND create_time < ?", startOfDay, endOfDay)
todayAgentOrderCount, err := l.svcCtx.AgentOrderModel.FindCount(l.ctx, todayBuilder, "id")
if err != nil {
logx.Errorf("查询今日代理订单数失败: %v", err)
return nil, fmt.Errorf("查询今日代理订单数失败: %w", err)
}
// 构建响应
resp = &types.AdminGetAgentOrderStatisticsResp{
TotalAgentOrderCount: totalAgentOrderCount,
TodayAgentOrderCount: todayAgentOrderCount,
}
return resp, nil
}

View File

@@ -0,0 +1,57 @@
package admin_agent
import (
"context"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/Masterminds/squirrel"
"github.com/jinzhu/copier"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetAgentPlatformDeductionListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetAgentPlatformDeductionListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetAgentPlatformDeductionListLogic {
return &AdminGetAgentPlatformDeductionListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetAgentPlatformDeductionListLogic) AdminGetAgentPlatformDeductionList(req *types.AdminGetAgentPlatformDeductionListReq) (resp *types.AdminGetAgentPlatformDeductionListResp, err error) {
builder := l.svcCtx.AgentPlatformDeductionModel.SelectBuilder()
if req.AgentId != nil {
builder = builder.Where(squirrel.Eq{"agent_id": *req.AgentId})
}
if req.Type != nil && *req.Type != "" {
builder = builder.Where(squirrel.Eq{"type": *req.Type})
}
if req.Status != nil {
builder = builder.Where(squirrel.Eq{"status": *req.Status})
}
list, total, err := l.svcCtx.AgentPlatformDeductionModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
if err != nil {
return nil, err
}
items := make([]types.AgentPlatformDeductionListItem, 0, len(list))
for _, v := range list {
item := types.AgentPlatformDeductionListItem{}
_ = copier.Copy(&item, v)
item.CreateTime = v.CreateTime.Format("2006-01-02 15:04:05")
items = append(items, item)
}
resp = &types.AdminGetAgentPlatformDeductionListResp{
Total: total,
Items: items,
}
return
}

View File

@@ -0,0 +1,74 @@
package admin_agent
import (
"context"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/Masterminds/squirrel"
"github.com/jinzhu/copier"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetAgentProductionConfigListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetAgentProductionConfigListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetAgentProductionConfigListLogic {
return &AdminGetAgentProductionConfigListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetAgentProductionConfigListLogic) AdminGetAgentProductionConfigList(req *types.AdminGetAgentProductionConfigListReq) (resp *types.AdminGetAgentProductionConfigListResp, err error) {
builder := l.svcCtx.AgentProductConfigModel.SelectBuilder()
if req.ProductName != nil && *req.ProductName != "" {
products, err := l.svcCtx.ProductModel.FindAll(l.ctx, l.svcCtx.ProductModel.SelectBuilder().Where(squirrel.Eq{"product_name": *req.ProductName}), "")
if err != nil || len(products) == 0 {
return &types.AdminGetAgentProductionConfigListResp{Total: 0, Items: []types.AgentProductionConfigItem{}}, nil
}
builder = builder.Where(squirrel.Eq{"product_id": products[0].Id})
}
if req.Id != nil {
builder = builder.Where(squirrel.Eq{"id": *req.Id})
}
list, total, err := l.svcCtx.AgentProductConfigModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
if err != nil {
return nil, err
}
// 查询所有涉及到的product_id对应的product_name
productIdSet := make(map[int64]struct{})
for _, v := range list {
productIdSet[v.ProductId] = struct{}{}
}
productIdArr := make([]int64, 0, len(productIdSet))
for id := range productIdSet {
productIdArr = append(productIdArr, id)
}
productNameMap := make(map[int64]string)
if len(productIdArr) > 0 {
build := l.svcCtx.ProductModel.SelectBuilder().Where(squirrel.Eq{"id": productIdArr})
products, _ := l.svcCtx.ProductModel.FindAll(l.ctx, build, "")
for _, p := range products {
productNameMap[p.Id] = p.ProductName
}
}
items := make([]types.AgentProductionConfigItem, 0, len(list))
for _, v := range list {
item := types.AgentProductionConfigItem{}
_ = copier.Copy(&item, v)
item.ProductName = productNameMap[v.ProductId]
item.CreateTime = v.CreateTime.Format("2006-01-02 15:04:05")
items = append(items, item)
}
resp = &types.AdminGetAgentProductionConfigListResp{
Total: total,
Items: items,
}
return
}

View File

@@ -0,0 +1,58 @@
package admin_agent
import (
"context"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/Masterminds/squirrel"
"github.com/jinzhu/copier"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetAgentRewardListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetAgentRewardListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetAgentRewardListLogic {
return &AdminGetAgentRewardListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetAgentRewardListLogic) AdminGetAgentRewardList(req *types.AdminGetAgentRewardListReq) (resp *types.AdminGetAgentRewardListResp, err error) {
builder := l.svcCtx.AgentRewardsModel.SelectBuilder()
if req.AgentId != nil {
builder = builder.Where(squirrel.Eq{"agent_id": *req.AgentId})
}
if req.RelationAgentId != nil {
builder = builder.Where(squirrel.Eq{"relation_agent_id": *req.RelationAgentId})
}
if req.Type != nil && *req.Type != "" {
builder = builder.Where(squirrel.Eq{"type": *req.Type})
}
list, total, err := l.svcCtx.AgentRewardsModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
if err != nil {
return nil, err
}
items := make([]types.AgentRewardListItem, 0, len(list))
for _, v := range list {
item := types.AgentRewardListItem{}
_ = copier.Copy(&item, v)
item.CreateTime = v.CreateTime.Format("2006-01-02 15:04:05")
if v.RelationAgentId.Valid {
item.RelationAgentId = v.RelationAgentId.Int64
}
items = append(items, item)
}
resp = &types.AdminGetAgentRewardListResp{
Total: total,
Items: items,
}
return
}

View File

@@ -0,0 +1,56 @@
package admin_agent
import (
"context"
"fmt"
"time"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetAgentStatisticsLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetAgentStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetAgentStatisticsLogic {
return &AdminGetAgentStatisticsLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetAgentStatisticsLogic) AdminGetAgentStatistics(req *types.AdminGetAgentStatisticsReq) (resp *types.AdminGetAgentStatisticsResp, err error) {
// 使用AgentModel的SelectBuilder和FindCount方法获取总代理数
totalBuilder := l.svcCtx.AgentModel.SelectBuilder()
totalAgentCount, err := l.svcCtx.AgentModel.FindCount(l.ctx, totalBuilder, "id")
if err != nil {
logx.Errorf("获取总代理数失败: %v", err)
return nil, fmt.Errorf("获取总代理数失败: %w", err)
}
// 获取今日新增代理数
todayBuilder := l.svcCtx.AgentModel.SelectBuilder()
today := time.Now()
startOfDay := time.Date(today.Year(), today.Month(), today.Day(), 0, 0, 0, 0, today.Location())
endOfDay := startOfDay.Add(24 * time.Hour)
todayBuilder = todayBuilder.Where("create_time >= ? AND create_time < ?", startOfDay, endOfDay)
todayAgentCount, err := l.svcCtx.AgentModel.FindCount(l.ctx, todayBuilder, "id")
if err != nil {
logx.Errorf("获取今日新增代理数失败: %v", err)
return nil, fmt.Errorf("获取今日新增代理数失败: %w", err)
}
resp = &types.AdminGetAgentStatisticsResp{
TotalAgentCount: totalAgentCount,
TodayAgentCount: todayAgentCount,
}
return resp, nil
}

View File

@@ -0,0 +1,45 @@
package admin_agent
import (
"context"
"errors"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"tyass-server/app/main/model"
"tyass-server/common/xerr"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetAgentWalletLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetAgentWalletLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetAgentWalletLogic {
return &AdminGetAgentWalletLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetAgentWalletLogic) AdminGetAgentWallet(req *types.AdminGetAgentWalletReq) (resp *types.AdminGetAgentWalletResp, err error) {
// 查询代理钱包信息
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(l.ctx, req.AgentId)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return nil, xerr.NewErrMsg("代理钱包不存在")
}
return nil, err
}
resp = &types.AdminGetAgentWalletResp{
Balance: wallet.Balance,
FrozenBalance: wallet.FrozenBalance,
TotalEarnings: wallet.TotalEarnings,
}
return
}

View File

@@ -0,0 +1,84 @@
package admin_agent
import (
"context"
"errors"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/Masterminds/squirrel"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetAgentWalletTransactionListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetAgentWalletTransactionListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetAgentWalletTransactionListLogic {
return &AdminGetAgentWalletTransactionListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetAgentWalletTransactionListLogic) AdminGetAgentWalletTransactionList(req *types.AdminGetAgentWalletTransactionListReq) (resp *types.AdminGetAgentWalletTransactionListResp, err error) {
builder := l.svcCtx.AgentWalletTransactionModel.SelectBuilder()
// 必须传入代理ID
if req.AgentId == 0 {
return nil, errors.New("代理ID不能为空")
}
builder = builder.Where(squirrel.Eq{"agent_id": req.AgentId})
// 可选条件
if req.TransactionType != nil && *req.TransactionType != "" {
builder = builder.Where(squirrel.Eq{"transaction_type": *req.TransactionType})
}
if req.CreateTimeStart != nil && *req.CreateTimeStart != "" {
builder = builder.Where(squirrel.GtOrEq{"create_time": *req.CreateTimeStart})
}
if req.CreateTimeEnd != nil && *req.CreateTimeEnd != "" {
builder = builder.Where(squirrel.LtOrEq{"create_time": *req.CreateTimeEnd})
}
list, total, err := l.svcCtx.AgentWalletTransactionModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
if err != nil {
return nil, err
}
items := make([]types.AgentWalletTransactionListItem, 0, len(list))
for _, v := range list {
item := types.AgentWalletTransactionListItem{
Id: v.Id,
AgentId: v.AgentId,
TransactionType: v.TransactionType,
Amount: v.Amount,
BalanceBefore: v.BalanceBefore,
BalanceAfter: v.BalanceAfter,
FrozenBalanceBefore: v.FrozenBalanceBefore,
FrozenBalanceAfter: v.FrozenBalanceAfter,
CreateTime: v.CreateTime.Format("2006-01-02 15:04:05"),
}
if v.TransactionId.Valid {
item.TransactionId = &v.TransactionId.String
}
if v.RelatedUserId.Valid {
item.RelatedUserId = &v.RelatedUserId.Int64
}
if v.Remark.Valid {
item.Remark = &v.Remark.String
}
items = append(items, item)
}
resp = &types.AdminGetAgentWalletTransactionListResp{
Total: total,
Items: items,
}
return
}

View File

@@ -0,0 +1,75 @@
package admin_agent
import (
"context"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/Masterminds/squirrel"
"github.com/jinzhu/copier"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetAgentWithdrawalListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetAgentWithdrawalListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetAgentWithdrawalListLogic {
return &AdminGetAgentWithdrawalListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetAgentWithdrawalListLogic) AdminGetAgentWithdrawalList(req *types.AdminGetAgentWithdrawalListReq) (resp *types.AdminGetAgentWithdrawalListResp, err error) {
builder := l.svcCtx.AgentWithdrawalModel.SelectBuilder()
if req.AgentId != nil {
builder = builder.Where(squirrel.Eq{"agent_id": *req.AgentId})
}
if req.Status != nil {
builder = builder.Where(squirrel.Eq{"status": *req.Status})
}
if req.WithdrawNo != nil && *req.WithdrawNo != "" {
builder = builder.Where(squirrel.Eq{"withdraw_no": *req.WithdrawNo})
}
if req.WithdrawType != nil {
builder = builder.Where(squirrel.Eq{"withdraw_type": *req.WithdrawType})
}
list, total, err := l.svcCtx.AgentWithdrawalModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
if err != nil {
return nil, err
}
items := make([]types.AgentWithdrawalListItem, 0, len(list))
for _, v := range list {
item := types.AgentWithdrawalListItem{}
_ = copier.Copy(&item, v)
item.Remark = ""
if v.Remark.Valid {
item.Remark = v.Remark.String
}
item.CreateTime = v.CreateTime.Format("2006-01-02 15:04:05")
// 手动设置银行卡信息copier不会自动处理sql.NullString
item.WithdrawType = v.WithdrawType
if v.BankCardNo.Valid {
item.BankCardNo = v.BankCardNo.String
}
if v.BankName.Valid {
item.BankName = v.BankName.String
}
if v.PayeeName.Valid {
item.PayeeName = v.PayeeName.String
}
items = append(items, item)
}
resp = &types.AdminGetAgentWithdrawalListResp{
Total: total,
Items: items,
}
return
}

View File

@@ -0,0 +1,31 @@
package admin_agent
import (
"context"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetSystemConfigLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetSystemConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetSystemConfigLogic {
return &AdminGetSystemConfigLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetSystemConfigLogic) AdminGetSystemConfig() (resp *types.AdminGetSystemConfigResp, err error) {
resp = &types.AdminGetSystemConfigResp{
CommissionSafeMode: l.svcCtx.Config.SystemConfig.CommissionSafeMode,
}
return
}

View File

@@ -0,0 +1,76 @@
package admin_agent
import (
"context"
"fmt"
"time"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetWithdrawalStatisticsLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetWithdrawalStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetWithdrawalStatisticsLogic {
return &AdminGetWithdrawalStatisticsLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetWithdrawalStatisticsLogic) AdminGetWithdrawalStatistics(req *types.AdminGetWithdrawalStatisticsReq) (resp *types.AdminGetWithdrawalStatisticsResp, err error) {
// 获取今日的开始和结束时间
today := time.Now()
startOfDay := time.Date(today.Year(), today.Month(), today.Day(), 0, 0, 0, 0, today.Location())
endOfDay := startOfDay.Add(24 * time.Hour)
// 构建查询条件
builder := l.svcCtx.AgentWithdrawalModel.SelectBuilder()
// 查询总提现金额status=2表示成功
totalBuilder := builder.Where("status = ?", 2)
totalWithdrawalAmount, err := l.svcCtx.AgentWithdrawalModel.FindSum(l.ctx, totalBuilder, "amount")
if err != nil {
logx.Errorf("查询总提现金额失败: %v", err)
return nil, fmt.Errorf("查询总提现金额失败: %w", err)
}
// 查询今日提现金额status=2表示成功
todayBuilder := builder.Where("status = ? AND create_time >= ? AND create_time < ?", 2, startOfDay, endOfDay)
todayWithdrawalAmount, err := l.svcCtx.AgentWithdrawalModel.FindSum(l.ctx, todayBuilder, "amount")
if err != nil {
logx.Errorf("查询今日提现金额失败: %v", err)
return nil, fmt.Errorf("查询今日提现金额失败: %w", err)
}
// 查询总实际到账金额status=2表示成功
totalActualAmount, err := l.svcCtx.AgentWithdrawalModel.FindSum(l.ctx, totalBuilder, "actual_amount")
if err != nil {
logx.Errorf("查询总实际到账金额失败: %v", err)
return nil, fmt.Errorf("查询总实际到账金额失败: %w", err)
}
// 查询总扣税金额status=2表示成功
totalTaxAmount, err := l.svcCtx.AgentWithdrawalModel.FindSum(l.ctx, totalBuilder, "tax_amount")
if err != nil {
logx.Errorf("查询总扣税金额失败: %v", err)
return nil, fmt.Errorf("查询总扣税金额失败: %w", err)
}
// 构建响应
resp = &types.AdminGetWithdrawalStatisticsResp{
TotalWithdrawalAmount: totalWithdrawalAmount,
TodayWithdrawalAmount: todayWithdrawalAmount,
TotalActualAmount: totalActualAmount,
TotalTaxAmount: totalTaxAmount,
}
return resp, nil
}

View File

@@ -0,0 +1,447 @@
package admin_agent
import (
"context"
"database/sql"
"time"
"tyass-server/app/main/model"
"tyass-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
// 审核操作常量
const (
ReviewActionApprove = 1 // 确认
ReviewActionReject = 2 // 拒绝
)
// 状态常量
const (
StatusPending = 1 // 申请中/处理中
StatusSuccess = 2 // 成功
StatusFailed = 3 // 失败
)
// 提现类型常量
const (
WithdrawTypeAlipay = 1 // 支付宝提现
WithdrawTypeBankCard = 2 // 银行卡提现
)
type AdminReviewBankCardWithdrawalLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminReviewBankCardWithdrawalLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminReviewBankCardWithdrawalLogic {
return &AdminReviewBankCardWithdrawalLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminReviewBankCardWithdrawalLogic) AdminReviewBankCardWithdrawal(req *types.AdminReviewBankCardWithdrawalReq) (resp *types.AdminReviewBankCardWithdrawalResp, err error) {
// 验证操作类型
if req.Action != ReviewActionApprove && req.Action != ReviewActionReject {
return nil, errors.Wrapf(xerr.NewErrMsg("操作类型不正确"), "操作类型验证失败")
}
// 拒绝操作必须填写备注
if req.Action == ReviewActionReject && req.Remark == "" {
return nil, errors.Wrapf(xerr.NewErrMsg("拒绝提现必须填写拒绝原因"), "拒绝原因验证失败")
}
resp = &types.AdminReviewBankCardWithdrawalResp{
Success: false,
}
// 使用事务处理审核操作
err = l.svcCtx.AgentModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
// 获取提现记录
record, err := l.svcCtx.AgentWithdrawalModel.FindOne(ctx, req.WithdrawalId)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return errors.Wrapf(xerr.NewErrMsg("提现记录不存在"), "提现记录不存在")
}
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询提现记录失败: %v", err)
}
// 验证提现记录状态必须是申请中
if record.Status != StatusPending {
return errors.Wrapf(xerr.NewErrMsg("该提现记录已处理,无法重复操作"), "状态验证失败")
}
// 验证提现类型(支持银行卡和支付宝提现)
if record.WithdrawType != WithdrawTypeBankCard && record.WithdrawType != WithdrawTypeAlipay {
return errors.Wrapf(xerr.NewErrMsg("提现类型不正确"), "提现类型验证失败")
}
if req.Action == ReviewActionApprove {
// 确认提现
return l.approveWithdrawal(ctx, session, record)
} else {
// 拒绝提现
return l.rejectWithdrawal(ctx, session, record, req.Remark)
}
})
if err != nil {
return nil, err
}
resp.Success = true
return resp, nil
}
// 确认提现
func (l *AdminReviewBankCardWithdrawalLogic) approveWithdrawal(ctx context.Context, session sqlx.Session, record *model.AgentWithdrawal) error {
// 根据提现类型执行不同的操作
if record.WithdrawType == WithdrawTypeAlipay {
// 支付宝提现:先调用支付宝转账接口
return l.approveAlipayWithdrawal(ctx, session, record)
} else {
// 银行卡提现:直接更新状态为成功(线下转账)
return l.approveBankCardWithdrawal(ctx, session, record)
}
}
// 确认支付宝提现
func (l *AdminReviewBankCardWithdrawalLogic) approveAlipayWithdrawal(ctx context.Context, session sqlx.Session, record *model.AgentWithdrawal) error {
// 同步调用支付宝转账
transferResp, err := l.svcCtx.AlipayService.AliTransfer(ctx, record.PayeeAccount, record.PayeeName.String, record.ActualAmount, "公司提现", record.WithdrawNo)
if err != nil {
l.Logger.Errorf("【支付宝转账失败】withdrawNo:%s error:%v", record.WithdrawNo, err)
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "支付宝接口调用失败: %v", err)
}
switch {
case transferResp.Status == "SUCCESS":
// 立即处理成功状态
return l.completeWithdrawalSuccess(ctx, session, record)
case transferResp.Status == "FAIL" || transferResp.SubCode != "":
// 处理明确失败
errorMsg := l.mapAlipayError(transferResp.SubCode)
return l.completeWithdrawalFailure(ctx, session, record, errorMsg)
case transferResp.Status == "DEALING":
// 处理中状态,更新为处理中但不标记为最终状态
record.Remark = sql.NullString{String: "支付宝转账处理中", Valid: true}
if _, err := l.svcCtx.AgentWithdrawalModel.Update(ctx, session, record); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新提现记录失败: %v", err)
}
l.Logger.Infof("支付宝提现审核通过,转账处理中 withdrawalId:%d withdrawNo:%s", record.Id, record.WithdrawNo)
return nil
default:
// 未知状态按失败处理
return l.completeWithdrawalFailure(ctx, session, record, "支付宝返回未知状态")
}
}
// 确认银行卡提现
func (l *AdminReviewBankCardWithdrawalLogic) approveBankCardWithdrawal(ctx context.Context, session sqlx.Session, record *model.AgentWithdrawal) error {
// 更新提现记录状态为成功
record.Status = StatusSuccess
record.Remark = sql.NullString{String: "管理员确认提现", Valid: true}
if _, err := l.svcCtx.AgentWithdrawalModel.Update(ctx, session, record); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新提现记录失败: %v", err)
}
// 解冻资金并扣除FrozenBalance -= amount, Balance不变
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(ctx, record.AgentId)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询钱包失败: %v", err)
}
// 记录变动前的冻结余额
frozenBalanceBefore := wallet.FrozenBalance
// 更新钱包(减少冻结余额)
wallet.FrozenBalance -= record.Amount
if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, wallet); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新钱包失败: %v", err)
}
// 记录交易流水(提现成功)
err = l.svcCtx.AgentService.CreateWalletTransaction(
ctx,
session,
wallet.AgentId,
model.WalletTransactionTypeWithdraw,
-record.Amount, // 变动金额(负数表示减少)
wallet.Balance, // 变动前余额(不变)
wallet.Balance, // 变动后余额(不变)
frozenBalanceBefore, // 变动前冻结余额
wallet.FrozenBalance, // 变动后冻结余额
record.WithdrawNo, // 关联交易ID
0, // 关联用户ID
"提现审核通过", // 备注
)
if err != nil {
return err
}
// 更新扣税记录状态为成功
taxModel, err := l.svcCtx.AgentWithdrawalTaxModel.FindOneByWithdrawalId(ctx, record.Id)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询扣税记录失败: %v", err)
}
if taxModel.TaxStatus == model.TaxStatusPending {
taxModel.TaxStatus = model.TaxStatusSuccess // 扣税状态 = 成功
taxModel.TaxTime = sql.NullTime{Time: time.Now(), Valid: true}
if err := l.svcCtx.AgentWithdrawalTaxModel.UpdateWithVersion(ctx, session, taxModel); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新扣税记录失败: %v", err)
}
}
// 提现成功后,给上级代理发放提现奖励
withdrawRewardErr := l.svcCtx.AgentService.GiveWithdrawReward(ctx, record.AgentId, record.Amount, session)
if withdrawRewardErr != nil {
l.Logger.Errorf("发放提现奖励失败代理ID%d提现金额%f错误%+v", record.AgentId, record.Amount, withdrawRewardErr)
// 提现奖励失败不影响主流程,只记录日志
} else {
l.Logger.Infof("发放提现奖励成功代理ID%d提现金额%f", record.AgentId, record.Amount)
}
l.Logger.Infof("银行卡提现确认成功 withdrawalId:%d amount:%f", record.Id, record.Amount)
return nil
}
// 拒绝提现
func (l *AdminReviewBankCardWithdrawalLogic) rejectWithdrawal(ctx context.Context, session sqlx.Session, record *model.AgentWithdrawal, remark string) error {
// 更新提现记录状态为失败
record.Status = StatusFailed
record.Remark = sql.NullString{String: "管理员拒绝:" + remark, Valid: true}
if _, err := l.svcCtx.AgentWithdrawalModel.Update(ctx, session, record); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新提现记录失败: %v", err)
}
// 解冻资金FrozenBalance -= amount, Balance += amount
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(ctx, record.AgentId)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询钱包失败: %v", err)
}
// 记录变动前的余额
balanceBefore := wallet.Balance
frozenBalanceBefore := wallet.FrozenBalance
// 更新钱包(余额增加,冻结余额减少)
wallet.Balance += record.Amount
wallet.FrozenBalance -= record.Amount
if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, wallet); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新钱包失败: %v", err)
}
// 记录交易流水(解冻)
err = l.svcCtx.AgentService.CreateWalletTransaction(
ctx,
session,
wallet.AgentId,
model.WalletTransactionTypeUnfreeze,
record.Amount, // 变动金额(正数表示增加)
balanceBefore, // 变动前余额
wallet.Balance, // 变动后余额
frozenBalanceBefore, // 变动前冻结余额
wallet.FrozenBalance, // 变动后冻结余额
record.WithdrawNo, // 关联交易ID
0, // 关联用户ID
"提现拒绝,解冻资金", // 备注
)
if err != nil {
return err
}
// 更新扣税记录状态为失败
taxModel, err := l.svcCtx.AgentWithdrawalTaxModel.FindOneByWithdrawalId(ctx, record.Id)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询扣税记录失败: %v", err)
}
if taxModel.TaxStatus == model.TaxStatusPending {
taxModel.TaxStatus = model.TaxStatusFailed // 扣税状态 = 失败
taxModel.TaxTime = sql.NullTime{Time: time.Now(), Valid: true}
if err := l.svcCtx.AgentWithdrawalTaxModel.UpdateWithVersion(ctx, session, taxModel); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新扣税记录失败: %v", err)
}
}
l.Logger.Infof("银行卡提现拒绝 withdrawalId:%d amount:%f reason:%s", record.Id, record.Amount, remark)
return nil
}
// 完成提现成功(支付宝转账成功后调用)
func (l *AdminReviewBankCardWithdrawalLogic) completeWithdrawalSuccess(ctx context.Context, session sqlx.Session, record *model.AgentWithdrawal) error {
// 更新提现记录状态为成功
record.Status = StatusSuccess
record.Remark = sql.NullString{String: "支付宝转账成功", Valid: true}
if _, err := l.svcCtx.AgentWithdrawalModel.Update(ctx, session, record); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新提现记录失败: %v", err)
}
// 解冻资金并扣除FrozenBalance -= amount, Balance不变
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(ctx, record.AgentId)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询钱包失败: %v", err)
}
// 记录变动前的冻结余额
frozenBalanceBefore := wallet.FrozenBalance
// 更新钱包(减少冻结余额)
wallet.FrozenBalance -= record.Amount
if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, wallet); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新钱包失败: %v", err)
}
// 记录交易流水(提现成功)
err = l.svcCtx.AgentService.CreateWalletTransaction(
ctx,
session,
wallet.AgentId,
model.WalletTransactionTypeWithdraw,
-record.Amount, // 变动金额(负数表示减少)
wallet.Balance, // 变动前余额(不变)
wallet.Balance, // 变动后余额(不变)
frozenBalanceBefore, // 变动前冻结余额
wallet.FrozenBalance, // 变动后冻结余额
record.WithdrawNo, // 关联交易ID
0, // 关联用户ID
"提现成功", // 备注
)
if err != nil {
return err
}
// 更新扣税记录状态为成功
taxModel, err := l.svcCtx.AgentWithdrawalTaxModel.FindOneByWithdrawalId(ctx, record.Id)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询扣税记录失败: %v", err)
}
if taxModel.TaxStatus == model.TaxStatusPending {
taxModel.TaxStatus = model.TaxStatusSuccess // 扣税状态 = 成功
taxModel.TaxTime = sql.NullTime{Time: time.Now(), Valid: true}
if err := l.svcCtx.AgentWithdrawalTaxModel.UpdateWithVersion(ctx, session, taxModel); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新扣税记录失败: %v", err)
}
}
// 提现成功后,给上级代理发放提现奖励
withdrawRewardErr := l.svcCtx.AgentService.GiveWithdrawReward(ctx, record.AgentId, record.Amount, session)
if withdrawRewardErr != nil {
l.Logger.Errorf("发放提现奖励失败代理ID%d提现金额%f错误%+v", record.AgentId, record.Amount, withdrawRewardErr)
// 提现奖励失败不影响主流程,只记录日志
} else {
l.Logger.Infof("发放提现奖励成功代理ID%d提现金额%f", record.AgentId, record.Amount)
}
l.Logger.Infof("支付宝提现成功 withdrawalId:%d withdrawNo:%s", record.Id, record.WithdrawNo)
return nil
}
// 完成提现失败(支付宝转账失败后调用)
func (l *AdminReviewBankCardWithdrawalLogic) completeWithdrawalFailure(ctx context.Context, session sqlx.Session, record *model.AgentWithdrawal, errorMsg string) error {
// 更新提现记录状态为失败
record.Status = StatusFailed
record.Remark = sql.NullString{String: errorMsg, Valid: true}
if _, err := l.svcCtx.AgentWithdrawalModel.Update(ctx, session, record); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新提现记录失败: %v", err)
}
// 解冻资金FrozenBalance -= amount, Balance += amount
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(ctx, record.AgentId)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询钱包失败: %v", err)
}
// 记录变动前的余额
balanceBefore := wallet.Balance
frozenBalanceBefore := wallet.FrozenBalance
// 更新钱包(余额增加,冻结余额减少)
wallet.Balance += record.Amount
wallet.FrozenBalance -= record.Amount
if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, wallet); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新钱包失败: %v", err)
}
// 记录交易流水(解冻)
err = l.svcCtx.AgentService.CreateWalletTransaction(
ctx,
session,
wallet.AgentId,
model.WalletTransactionTypeUnfreeze,
record.Amount, // 变动金额(正数表示增加)
balanceBefore, // 变动前余额
wallet.Balance, // 变动后余额
frozenBalanceBefore, // 变动前冻结余额
wallet.FrozenBalance, // 变动后冻结余额
record.WithdrawNo, // 关联交易ID
0, // 关联用户ID
"提现失败,解冻资金", // 备注
)
if err != nil {
return err
}
// 更新扣税记录状态为失败
taxModel, err := l.svcCtx.AgentWithdrawalTaxModel.FindOneByWithdrawalId(ctx, record.Id)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询扣税记录失败: %v", err)
}
if taxModel.TaxStatus == model.TaxStatusPending {
taxModel.TaxStatus = model.TaxStatusFailed // 扣税状态 = 失败
taxModel.TaxTime = sql.NullTime{Time: time.Now(), Valid: true}
if err := l.svcCtx.AgentWithdrawalTaxModel.UpdateWithVersion(ctx, session, taxModel); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新扣税记录失败: %v", err)
}
}
l.Logger.Infof("支付宝提现失败 withdrawalId:%d withdrawNo:%s reason:%s", record.Id, record.WithdrawNo, errorMsg)
return nil
}
// 错误类型映射
func (l *AdminReviewBankCardWithdrawalLogic) mapAlipayError(code string) string {
errorMapping := map[string]string{
// 账户存在性错误
"PAYEE_ACCOUNT_NOT_EXSIT": "收款账户不存在,请检查账号是否正确",
"PAYEE_NOT_EXIST": "收款账户不存在或姓名有误,请核实信息",
"PAYEE_ACC_OCUPIED": "收款账号存在多个账户,无法确认唯一性",
"PAYEE_MID_CANNOT_SAME": "收款方和中间方不能是同一个人,请修改收款方或者中间方信息",
// 实名认证问题
"PAYEE_CERTIFY_LEVEL_LIMIT": "收款方未完成实名认证",
"PAYEE_NOT_RELNAME_CERTIFY": "收款方未完成实名认证",
"PAYEE_CERT_INFO_ERROR": "收款方证件信息不匹配",
// 账户状态异常
"PAYEE_ACCOUNT_STATUS_ERROR": "收款账户状态异常,请更换账号",
"PAYEE_USERINFO_STATUS_ERROR": "收款账户状态异常,无法收款",
"PERMIT_LIMIT_PAYEE": "收款账户异常,请更换账号",
"BLOCK_USER_FORBBIDEN_RECIEVE": "账户冻结无法收款",
"PAYEE_TRUSTEESHIP_ACC_OVER_LIMIT": "收款方托管子户累计收款金额超限",
// 账户信息错误
"PAYEE_USERINFO_ERROR": "收款方姓名或信息不匹配",
"PAYEE_CARD_INFO_ERROR": "收款支付宝账号及户名不一致",
"PAYEE_IDENTITY_NOT_MATCH": "收款方身份信息不匹配",
"PAYEE_USER_IS_INST": "收款方为金融机构,不能使用提现功能,请更换收款账号",
"PAYEE_USER_TYPE_ERROR": "该支付宝账号类型不支持提现,请更换收款账号",
// 权限与限制
"PAYEE_RECEIVE_COUNT_EXCEED_LIMIT": "收款次数超限,请明日再试",
"PAYEE_OUT_PERMLIMIT_CHECK_FAILURE": "收款方权限校验不通过",
"PERMIT_NON_BANK_LIMIT_PAYEE": "收款方未完善身份信息,无法收款",
}
if msg, ok := errorMapping[code]; ok {
return msg
}
return "系统错误,请联系客服"
}

View File

@@ -0,0 +1,109 @@
package admin_agent
import (
"context"
"errors"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"tyass-server/app/main/model"
"tyass-server/common/xerr"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
type AdminUpdateAgentCommissionStatusLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminUpdateAgentCommissionStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminUpdateAgentCommissionStatusLogic {
return &AdminUpdateAgentCommissionStatusLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminUpdateAgentCommissionStatusLogic) AdminUpdateAgentCommissionStatus(req *types.AdminUpdateAgentCommissionStatusReq) (resp *types.AdminUpdateAgentCommissionStatusResp, err error) {
// 验证状态值不允许手动设置为2已取消只能设置为0或1
if req.Status != 0 && req.Status != 1 {
return nil, xerr.NewErrMsg("无效的状态值状态必须为0(已结算)或1(冻结中)")
}
commission, err := l.svcCtx.AgentCommissionModel.FindOne(l.ctx, req.Id)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return nil, xerr.NewErrMsg("佣金记录不存在")
}
return nil, err
}
// 检查状态转换是否合法
// 0(已结算) <-> 1(冻结中):允许冻结和解冻相互转换
// 2(已取消):已取消的状态无法转换到其他状态(由订单退款自动触发)
if commission.Status == req.Status {
return nil, xerr.NewErrMsg("状态未发生变化")
}
// 已取消的状态不能再转换
if commission.Status == 2 {
return nil, xerr.NewErrMsg("已取消的佣金状态不能转换")
}
// 开始事务
err = l.svcCtx.AgentCommissionModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
// 保存原始状态用于判断
originalStatus := commission.Status
// 更新佣金状态
commission.Status = req.Status
err = l.svcCtx.AgentCommissionModel.UpdateWithVersion(ctx, session, commission)
if err != nil {
return err
}
// 查询代理钱包
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(ctx, commission.AgentId)
if err != nil {
return err
}
// 根据状态转换更新钱包
if originalStatus == 0 && req.Status == 1 {
// 已结算 -> 冻结中:增加冻结金额,减少钱包余额
// 检查钱包余额是否足够
if wallet.Balance < commission.Amount {
return xerr.NewErrMsg("钱包余额不足,无法冻结")
}
wallet.FrozenBalance += commission.Amount
wallet.Balance -= commission.Amount
} else if originalStatus == 1 && req.Status == 0 {
// 冻结中 -> 已结算:减少冻结金额,增加钱包余额
// 检查冻结余额是否足够
if wallet.FrozenBalance < commission.Amount {
return xerr.NewErrMsg("冻结余额不足,无法解冻")
}
wallet.FrozenBalance -= commission.Amount
wallet.Balance += commission.Amount
}
err = l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, wallet)
if err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
resp = &types.AdminUpdateAgentCommissionStatusResp{
Success: true,
}
return
}

View File

@@ -0,0 +1,96 @@
package admin_agent
import (
"context"
"database/sql"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminUpdateAgentMembershipConfigLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminUpdateAgentMembershipConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminUpdateAgentMembershipConfigLogic {
return &AdminUpdateAgentMembershipConfigLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminUpdateAgentMembershipConfigLogic) AdminUpdateAgentMembershipConfig(req *types.AdminUpdateAgentMembershipConfigReq) (resp *types.AdminUpdateAgentMembershipConfigResp, err error) {
cfg, err := l.svcCtx.AgentMembershipConfigModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, err
}
cfg.LevelName = req.LevelName
cfg.Price = sql.NullFloat64{Float64: req.Price, Valid: true}
cfg.ReportCommission = sql.NullFloat64{Float64: req.ReportCommission, Valid: true}
if req.LowerActivityReward == nil {
cfg.LowerActivityReward = sql.NullFloat64{Valid: false}
} else {
cfg.LowerActivityReward = sql.NullFloat64{Float64: *req.LowerActivityReward, Valid: true}
}
if req.NewActivityReward == nil {
cfg.NewActivityReward = sql.NullFloat64{Valid: false}
} else {
cfg.NewActivityReward = sql.NullFloat64{Float64: *req.NewActivityReward, Valid: true}
}
if req.LowerStandardCount == nil {
cfg.LowerStandardCount = sql.NullInt64{Valid: false}
} else {
cfg.LowerStandardCount = sql.NullInt64{Int64: *req.LowerStandardCount, Valid: true}
}
if req.NewLowerStandardCount == nil {
cfg.NewLowerStandardCount = sql.NullInt64{Valid: false}
} else {
cfg.NewLowerStandardCount = sql.NullInt64{Int64: *req.NewLowerStandardCount, Valid: true}
}
if req.LowerWithdrawRewardRatio == nil {
cfg.LowerWithdrawRewardRatio = sql.NullFloat64{Valid: false}
} else {
cfg.LowerWithdrawRewardRatio = sql.NullFloat64{Float64: *req.LowerWithdrawRewardRatio, Valid: true}
}
if req.LowerConvertVipReward == nil {
cfg.LowerConvertVipReward = sql.NullFloat64{Valid: false}
} else {
cfg.LowerConvertVipReward = sql.NullFloat64{Float64: *req.LowerConvertVipReward, Valid: true}
}
if req.LowerConvertSvipReward == nil {
cfg.LowerConvertSvipReward = sql.NullFloat64{Valid: false}
} else {
cfg.LowerConvertSvipReward = sql.NullFloat64{Float64: *req.LowerConvertSvipReward, Valid: true}
}
if req.ExemptionAmount == nil {
cfg.ExemptionAmount = sql.NullFloat64{Valid: false}
} else {
cfg.ExemptionAmount = sql.NullFloat64{Float64: *req.ExemptionAmount, Valid: true}
}
if req.PriceIncreaseMax == nil {
cfg.PriceIncreaseMax = sql.NullFloat64{Valid: false}
} else {
cfg.PriceIncreaseMax = sql.NullFloat64{Float64: *req.PriceIncreaseMax, Valid: true}
}
if req.PriceRatio == nil {
cfg.PriceRatio = sql.NullFloat64{Valid: false}
} else {
cfg.PriceRatio = sql.NullFloat64{Float64: *req.PriceRatio, Valid: true}
}
if req.PriceIncreaseAmount == nil {
cfg.PriceIncreaseAmount = sql.NullFloat64{Valid: false}
} else {
cfg.PriceIncreaseAmount = sql.NullFloat64{Float64: *req.PriceIncreaseAmount, Valid: true}
}
_, err = l.svcCtx.AgentMembershipConfigModel.Update(l.ctx, nil, cfg)
if err != nil {
return nil, err
}
resp = &types.AdminUpdateAgentMembershipConfigResp{Success: true}
return
}

View File

@@ -0,0 +1,42 @@
package admin_agent
import (
"context"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminUpdateAgentProductionConfigLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminUpdateAgentProductionConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminUpdateAgentProductionConfigLogic {
return &AdminUpdateAgentProductionConfigLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminUpdateAgentProductionConfigLogic) AdminUpdateAgentProductionConfig(req *types.AdminUpdateAgentProductionConfigReq) (resp *types.AdminUpdateAgentProductionConfigResp, err error) {
cfg, err := l.svcCtx.AgentProductConfigModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, err
}
cfg.CostPrice = req.CostPrice
cfg.PriceRangeMin = req.PriceRangeMin
cfg.PriceRangeMax = req.PriceRangeMax
cfg.PricingStandard = req.PricingStandard
cfg.OverpricingRatio = req.OverpricingRatio
_, err = l.svcCtx.AgentProductConfigModel.Update(l.ctx, nil, cfg)
if err != nil {
return nil, err
}
resp = &types.AdminUpdateAgentProductionConfigResp{Success: true}
return
}

View File

@@ -0,0 +1,107 @@
package admin_agent
import (
"context"
"errors"
"fmt"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"tyass-server/app/main/model"
"tyass-server/common/xerr"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
type AdminUpdateAgentWalletBalanceLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminUpdateAgentWalletBalanceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminUpdateAgentWalletBalanceLogic {
return &AdminUpdateAgentWalletBalanceLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminUpdateAgentWalletBalanceLogic) AdminUpdateAgentWalletBalance(req *types.AdminUpdateAgentWalletBalanceReq) (resp *types.AdminUpdateAgentWalletBalanceResp, err error) {
// 参数校验
if req.AgentId <= 0 {
return nil, xerr.NewErrMsg("代理ID无效")
}
if req.Amount == 0 {
return nil, xerr.NewErrMsg("修改金额不能为0")
}
// 查询代理钱包信息
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(l.ctx, req.AgentId)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return nil, xerr.NewErrMsg("代理钱包不存在")
}
return nil, err
}
// 计算新余额
newBalance := wallet.Balance + req.Amount
// 校验余额不能为负数
if newBalance < 0 {
return nil, xerr.NewErrMsg(fmt.Sprintf("操作后余额不能为负数,当前余额: %.2f,操作金额: %.2f", wallet.Balance, req.Amount))
}
// 更新余额
updateErr := l.svcCtx.AgentWalletModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error {
// 记录变动前的余额
balanceBefore := wallet.Balance
frozenBalanceBefore := wallet.FrozenBalance
// 使用版本号更新
wallet.Balance = newBalance
err := l.svcCtx.AgentWalletModel.UpdateWithVersion(transCtx, session, wallet)
if err != nil {
return err
}
// 创建钱包交易流水记录(手动调整)
remark := fmt.Sprintf("管理员手动调整余额,金额: %.2f", req.Amount)
transErr := l.svcCtx.AgentService.CreateWalletTransaction(
transCtx,
session,
req.AgentId,
model.WalletTransactionTypeAdjust,
req.Amount, // 变动金额(正数表示增加,负数表示减少)
balanceBefore, // 变动前余额
wallet.Balance, // 变动后余额
frozenBalanceBefore, // 变动前冻结余额
wallet.FrozenBalance, // 变动后冻结余额(保持不变)
"", // 关联交易ID无关联
0, // 关联用户ID无关联
remark, // 备注
)
if transErr != nil {
l.Logger.Errorf("创建代理钱包流水记录失败: %+v", transErr)
return transErr
}
l.Logger.Infof("代理钱包余额变更 - AgentId: %d, 原余额: %.2f, 变更金额: %.2f, 新余额: %.2f",
req.AgentId, balanceBefore, req.Amount, wallet.Balance)
return nil
})
if updateErr != nil {
l.Logger.Errorf("更新代理钱包余额失败: %+v", updateErr)
return nil, xerr.NewErrMsg("更新余额失败")
}
resp = &types.AdminUpdateAgentWalletBalanceResp{
Success: true,
Balance: newBalance,
}
return
}

View File

@@ -0,0 +1,37 @@
package admin_agent
import (
"context"
"tyass-server/app/main/api/internal/svc"
"tyass-server/app/main/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminUpdateSystemConfigLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminUpdateSystemConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminUpdateSystemConfigLogic {
return &AdminUpdateSystemConfigLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminUpdateSystemConfigLogic) AdminUpdateSystemConfig(req *types.AdminUpdateSystemConfigReq) (resp *types.AdminUpdateSystemConfigResp, err error) {
// 更新佣金安全防御模式配置
if req.CommissionSafeMode != nil {
l.svcCtx.Config.SystemConfig.CommissionSafeMode = *req.CommissionSafeMode
logx.Infof("更新系统配置:佣金安全防御模式设置为 %v", *req.CommissionSafeMode)
}
resp = &types.AdminUpdateSystemConfigResp{
Success: true,
}
return
}