v2.0
This commit is contained in:
parent
0d0ad3bee8
commit
26c403732a
@ -57,6 +57,14 @@ service main {
|
|||||||
// 获取推广定价配置
|
// 获取推广定价配置
|
||||||
@handler GetAgentProductConfig
|
@handler GetAgentProductConfig
|
||||||
get /product_config returns (AgentProductConfigResp)
|
get /product_config returns (AgentProductConfigResp)
|
||||||
|
|
||||||
|
// 获取下级分页列表
|
||||||
|
@handler GetAgentSubordinateList
|
||||||
|
get /subordinate/list (GetAgentSubordinateListReq) returns (GetAgentSubordinateListResp)
|
||||||
|
|
||||||
|
// 下级贡献详情
|
||||||
|
@handler GetAgentSubordinateContributionDetail
|
||||||
|
get /subordinate/contribution/detail (GetAgentSubordinateContributionDetailReq) returns (GetAgentSubordinateContributionDetailResp)
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@ -85,6 +93,63 @@ type (
|
|||||||
AgentProductConfigResp {
|
AgentProductConfigResp {
|
||||||
AgentProductConfig []AgentProductConfig
|
AgentProductConfig []AgentProductConfig
|
||||||
}
|
}
|
||||||
|
GetAgentSubordinateListReq {
|
||||||
|
Page int64 `form:"page"` // 页码
|
||||||
|
PageSize int64 `form:"page_size"` // 每页数据量
|
||||||
|
}
|
||||||
|
GetAgentSubordinateListResp {
|
||||||
|
Total int64 `json:"total"` // 总记录数
|
||||||
|
List []AgentSubordinateList `json:"list"` // 查询列表
|
||||||
|
}
|
||||||
|
AgentSubordinateList {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
CreateTime string `json:"create_time"`
|
||||||
|
LevelName string `json:"level_name"`
|
||||||
|
TotalOrders int64 `json:"total_orders"` // 总单量
|
||||||
|
TotalEarnings float64 `json:"total_earnings"` // 总金额
|
||||||
|
TotalContribution float64 `json:"total_contribution"` // 总贡献
|
||||||
|
}
|
||||||
|
GetAgentSubordinateContributionDetailReq {
|
||||||
|
Page int64 `form:"page"` // 页码
|
||||||
|
PageSize int64 `form:"page_size"` // 每页数据量
|
||||||
|
SubordinateID int64 `form:"subordinate_id"` // 下级ID
|
||||||
|
}
|
||||||
|
GetAgentSubordinateContributionDetailResp {
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
Total int64 `json:"total"` // 总记录数
|
||||||
|
CreateTime string `json:"create_time"`
|
||||||
|
TotalEarnings float64 `json:"total_earnings"` // 总金额
|
||||||
|
TotalContribution float64 `json:"total_contribution"` // 总贡献
|
||||||
|
TotalOrders int64 `json:"total_orders"` // 总单量
|
||||||
|
LevelName string `json:"level_name"` // 等级名称
|
||||||
|
List []AgentSubordinateContributionDetail `json:"list"` // 查询列表
|
||||||
|
Stats AgentSubordinateContributionStats `json:"stats"` // 统计数据
|
||||||
|
}
|
||||||
|
AgentSubordinateContributionDetail {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
CreateTime string `json:"create_time"`
|
||||||
|
Amount float64 `json:"amount"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
AgentSubordinateContributionStats {
|
||||||
|
CostCount int64 `json:"cost_count"` // 成本扣除次数
|
||||||
|
CostAmount float64 `json:"cost_amount"` // 成本扣除总额
|
||||||
|
PricingCount int64 `json:"pricing_count"` // 定价扣除次数
|
||||||
|
PricingAmount float64 `json:"pricing_amount"` // 定价扣除总额
|
||||||
|
DescendantPromotionCount int64 `json:"descendant_promotion_count"` // 下级推广次数
|
||||||
|
DescendantPromotionAmount float64 `json:"descendant_promotion_amount"` // 下级推广总额
|
||||||
|
DescendantUpgradeVipCount int64 `json:"descendant_upgrade_vip_count"` // 下级升级VIP次数
|
||||||
|
DescendantUpgradeVipAmount float64 `json:"descendant_upgrade_vip_amount"` // 下级升级VIP总额
|
||||||
|
DescendantUpgradeSvipCount int64 `json:"descendant_upgrade_svip_count"` // 下级升级SVIP次数
|
||||||
|
DescendantUpgradeSvipAmount float64 `json:"descendant_upgrade_svip_amount"` // 下级升级SVIP总额
|
||||||
|
DescendantStayActiveCount int64 `json:"descendant_stay_active_count"` // 下级保持活跃次数
|
||||||
|
DescendantStayActiveAmount float64 `json:"descendant_stay_active_amount"` // 下级保持活跃总额
|
||||||
|
DescendantNewActiveCount int64 `json:"descendant_new_active_count"` // 下级新增活跃次数
|
||||||
|
DescendantNewActiveAmount float64 `json:"descendant_new_active_amount"` // 下级新增活跃总额
|
||||||
|
DescendantWithdrawCount int64 `json:"descendant_withdraw_count"` // 下级提现次数
|
||||||
|
DescendantWithdrawAmount float64 `json:"descendant_withdraw_amount"` // 下级提现总额
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@server (
|
@server (
|
||||||
|
@ -45,6 +45,8 @@ Wxpay:
|
|||||||
MchCertificateSerialNumber: "5369B8AEEBDCF7AF274510252E6A8C0659C30F61"
|
MchCertificateSerialNumber: "5369B8AEEBDCF7AF274510252E6A8C0659C30F61"
|
||||||
MchApiv3Key: "e3ea4cf0765f1e71b01bb387dfcdbc9f"
|
MchApiv3Key: "e3ea4cf0765f1e71b01bb387dfcdbc9f"
|
||||||
MchPrivateKeyPath: "etc/merchant/apiclient_key.pem"
|
MchPrivateKeyPath: "etc/merchant/apiclient_key.pem"
|
||||||
|
MchPublicKeyID: "XXXXXX"
|
||||||
|
MchPublicKeyPath: "etc/merchant/pub_key.pem"
|
||||||
NotifyUrl: "https://6m4685017o.goho.co/api/v1/pay/wechat/callback"
|
NotifyUrl: "https://6m4685017o.goho.co/api/v1/pay/wechat/callback"
|
||||||
RefundNotifyUrl: "https://6m4685017o.goho.co/api/v1/wechat/refund_callback"
|
RefundNotifyUrl: "https://6m4685017o.goho.co/api/v1/wechat/refund_callback"
|
||||||
Applepay:
|
Applepay:
|
||||||
|
@ -46,6 +46,8 @@ Wxpay:
|
|||||||
MchCertificateSerialNumber: "5369B8AEEBDCF7AF274510252E6A8C0659C30F61"
|
MchCertificateSerialNumber: "5369B8AEEBDCF7AF274510252E6A8C0659C30F61"
|
||||||
MchApiv3Key: "e3ea4cf0765f1e71b01bb387dfcdbc9f"
|
MchApiv3Key: "e3ea4cf0765f1e71b01bb387dfcdbc9f"
|
||||||
MchPrivateKeyPath: "etc/merchant/apiclient_key.pem"
|
MchPrivateKeyPath: "etc/merchant/apiclient_key.pem"
|
||||||
|
MchPublicKeyID: "XXXXXX"
|
||||||
|
MchPublicKeyPath: "etc/merchant/pub_key.pem"
|
||||||
NotifyUrl: "https://www.quannengcha.com/api/v1/pay/wechat/callback"
|
NotifyUrl: "https://www.quannengcha.com/api/v1/pay/wechat/callback"
|
||||||
RefundNotifyUrl: "https://www.quannengcha.com/api/v1/wechat/refund_callback"
|
RefundNotifyUrl: "https://www.quannengcha.com/api/v1/wechat/refund_callback"
|
||||||
Applepay:
|
Applepay:
|
||||||
|
@ -56,6 +56,8 @@ type WxpayConfig struct {
|
|||||||
MchCertificateSerialNumber string
|
MchCertificateSerialNumber string
|
||||||
MchApiv3Key string
|
MchApiv3Key string
|
||||||
MchPrivateKeyPath string
|
MchPrivateKeyPath string
|
||||||
|
MchPublicKeyID string
|
||||||
|
MchPublicKeyPath string
|
||||||
NotifyUrl string
|
NotifyUrl string
|
||||||
RefundNotifyUrl string
|
RefundNotifyUrl string
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"qnc-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"qnc-server/app/user/cmd/api/internal/svc"
|
||||||
|
"qnc-server/app/user/cmd/api/internal/types"
|
||||||
|
"qnc-server/common/result"
|
||||||
|
"qnc-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetAgentSubordinateContributionDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.GetAgentSubordinateContributionDetailReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := agent.NewGetAgentSubordinateContributionDetailLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetAgentSubordinateContributionDetail(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"qnc-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"qnc-server/app/user/cmd/api/internal/svc"
|
||||||
|
"qnc-server/app/user/cmd/api/internal/types"
|
||||||
|
"qnc-server/common/result"
|
||||||
|
"qnc-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetAgentSubordinateListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.GetAgentSubordinateListReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := agent.NewGetAgentSubordinateListLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetAgentSubordinateList(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -3,12 +3,13 @@ package pay
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/rest/httpx"
|
|
||||||
"qnc-server/app/user/cmd/api/internal/logic/pay"
|
"qnc-server/app/user/cmd/api/internal/logic/pay"
|
||||||
"qnc-server/app/user/cmd/api/internal/svc"
|
"qnc-server/app/user/cmd/api/internal/svc"
|
||||||
"qnc-server/app/user/cmd/api/internal/types"
|
"qnc-server/app/user/cmd/api/internal/types"
|
||||||
"qnc-server/common/result"
|
"qnc-server/common/result"
|
||||||
"qnc-server/pkg/lzkit/validator"
|
"qnc-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func PaymentCheckHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
func PaymentCheckHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
@ -40,6 +40,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
Path: "/product_config",
|
Path: "/product_config",
|
||||||
Handler: agent.GetAgentProductConfigHandler(serverCtx),
|
Handler: agent.GetAgentProductConfigHandler(serverCtx),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/subordinate/contribution/detail",
|
||||||
|
Handler: agent.GetAgentSubordinateContributionDetailHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/subordinate/list",
|
||||||
|
Handler: agent.GetAgentSubordinateListHandler(serverCtx),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
|
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
|
||||||
rest.WithPrefix("/api/v1/agent"),
|
rest.WithPrefix("/api/v1/agent"),
|
||||||
|
@ -3,12 +3,13 @@ package user
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/rest/httpx"
|
|
||||||
"qnc-server/app/user/cmd/api/internal/logic/user"
|
"qnc-server/app/user/cmd/api/internal/logic/user"
|
||||||
"qnc-server/app/user/cmd/api/internal/svc"
|
"qnc-server/app/user/cmd/api/internal/svc"
|
||||||
"qnc-server/app/user/cmd/api/internal/types"
|
"qnc-server/app/user/cmd/api/internal/types"
|
||||||
"qnc-server/common/result"
|
"qnc-server/common/result"
|
||||||
"qnc-server/pkg/lzkit/validator"
|
"qnc-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BindMobileHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
func BindMobileHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
@ -0,0 +1,200 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"qnc-server/app/user/cmd/api/internal/svc"
|
||||||
|
"qnc-server/app/user/cmd/api/internal/types"
|
||||||
|
"qnc-server/common/ctxdata"
|
||||||
|
"qnc-server/common/xerr"
|
||||||
|
"qnc-server/pkg/lzkit/crypto"
|
||||||
|
|
||||||
|
"github.com/Masterminds/squirrel"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetAgentSubordinateContributionDetailLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetAgentSubordinateContributionDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentSubordinateContributionDetailLogic {
|
||||||
|
return &GetAgentSubordinateContributionDetailLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetAgentSubordinateContributionDetailLogic) GetAgentSubordinateContributionDetail(req *types.GetAgentSubordinateContributionDetailReq) (resp *types.GetAgentSubordinateContributionDetailResp, err error) {
|
||||||
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理下级贡献详情, 获取用户ID%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前代理信息
|
||||||
|
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取代理信息%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取下级代理信息
|
||||||
|
subordinateAgent, err := l.svcCtx.AgentModel.FindOne(l.ctx, req.SubordinateID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取下级代理信息%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证是否是当前代理的下级
|
||||||
|
closureBuilder := l.svcCtx.AgentClosureModel.SelectBuilder().Where(squirrel.Eq{
|
||||||
|
"ancestor_id": agentModel.Id,
|
||||||
|
"descendant_id": req.SubordinateID,
|
||||||
|
})
|
||||||
|
closureList, err := l.svcCtx.AgentClosureModel.FindAll(l.ctx, closureBuilder, "create_time DESC")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 验证代理关系%v", err)
|
||||||
|
}
|
||||||
|
if len(closureList) == 0 {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理下级贡献详情, 非法的代理关系")
|
||||||
|
}
|
||||||
|
closure := closureList[0]
|
||||||
|
|
||||||
|
// 获取佣金扣除记录
|
||||||
|
deductionBuilder := l.svcCtx.AgentCommissionDeductionModel.SelectBuilder().Where(squirrel.Eq{
|
||||||
|
"agent_id": agentModel.Id,
|
||||||
|
"deducted_agent_id": req.SubordinateID,
|
||||||
|
})
|
||||||
|
deductionList, err := l.svcCtx.AgentCommissionDeductionModel.FindAll(l.ctx, deductionBuilder, "create_time DESC")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取佣金扣除记录%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取奖励记录
|
||||||
|
rewardsBuilder := l.svcCtx.AgentRewardsModel.SelectBuilder().Where(squirrel.Eq{
|
||||||
|
"agent_id": agentModel.Id,
|
||||||
|
"relation_agent_id": req.SubordinateID,
|
||||||
|
})
|
||||||
|
rewards, err := l.svcCtx.AgentRewardsModel.FindAll(l.ctx, rewardsBuilder, "create_time DESC")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取奖励记录%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算总贡献
|
||||||
|
var totalContribution float64
|
||||||
|
for _, v := range deductionList {
|
||||||
|
totalContribution += v.Amount
|
||||||
|
}
|
||||||
|
// 加上奖励金额
|
||||||
|
for _, v := range rewards {
|
||||||
|
totalContribution += v.Amount
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取佣金记录
|
||||||
|
commissionBuilder := l.svcCtx.AgentCommissionModel.SelectBuilder().Where(squirrel.Eq{
|
||||||
|
"agent_id": req.SubordinateID,
|
||||||
|
})
|
||||||
|
commissionList, err := l.svcCtx.AgentCommissionModel.FindAll(l.ctx, commissionBuilder, "create_time DESC")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取佣金记录%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算总收益和总单量
|
||||||
|
var totalEarnings float64
|
||||||
|
for _, v := range commissionList {
|
||||||
|
totalEarnings += v.Amount
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化统计数据
|
||||||
|
stats := types.AgentSubordinateContributionStats{
|
||||||
|
CostCount: 0,
|
||||||
|
CostAmount: 0,
|
||||||
|
PricingCount: 0,
|
||||||
|
PricingAmount: 0,
|
||||||
|
DescendantPromotionCount: 0,
|
||||||
|
DescendantPromotionAmount: 0,
|
||||||
|
DescendantUpgradeVipCount: 0,
|
||||||
|
DescendantUpgradeVipAmount: 0,
|
||||||
|
DescendantUpgradeSvipCount: 0,
|
||||||
|
DescendantUpgradeSvipAmount: 0,
|
||||||
|
DescendantStayActiveCount: 0,
|
||||||
|
DescendantStayActiveAmount: 0,
|
||||||
|
DescendantNewActiveCount: 0,
|
||||||
|
DescendantNewActiveAmount: 0,
|
||||||
|
DescendantWithdrawCount: 0,
|
||||||
|
DescendantWithdrawAmount: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统计佣金扣除记录
|
||||||
|
for _, v := range deductionList {
|
||||||
|
switch v.Type {
|
||||||
|
case "cost":
|
||||||
|
stats.CostCount++
|
||||||
|
stats.CostAmount += v.Amount
|
||||||
|
case "pricing":
|
||||||
|
stats.PricingCount++
|
||||||
|
stats.PricingAmount += v.Amount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统计奖励记录
|
||||||
|
for _, v := range rewards {
|
||||||
|
switch v.Type {
|
||||||
|
case "descendant_promotion":
|
||||||
|
stats.DescendantPromotionCount++
|
||||||
|
stats.DescendantPromotionAmount += v.Amount
|
||||||
|
case "descendant_upgrade_vip":
|
||||||
|
stats.DescendantUpgradeVipCount++
|
||||||
|
stats.DescendantUpgradeVipAmount += v.Amount
|
||||||
|
case "descendant_upgrade_svip":
|
||||||
|
stats.DescendantUpgradeSvipCount++
|
||||||
|
stats.DescendantUpgradeSvipAmount += v.Amount
|
||||||
|
case "descendant_stay_active":
|
||||||
|
stats.DescendantStayActiveCount++
|
||||||
|
stats.DescendantStayActiveAmount += v.Amount
|
||||||
|
case "descendant_new_active":
|
||||||
|
stats.DescendantNewActiveCount++
|
||||||
|
stats.DescendantNewActiveAmount += v.Amount
|
||||||
|
case "descendant_withdraw":
|
||||||
|
stats.DescendantWithdrawCount++
|
||||||
|
stats.DescendantWithdrawAmount += v.Amount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解密手机号
|
||||||
|
secretKey := l.svcCtx.Config.Encrypt.SecretKey
|
||||||
|
mobile, err := crypto.DecryptMobile(subordinateAgent.Mobile, secretKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理下级贡献详情, 解密手机号失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取合并后的分页列表
|
||||||
|
unionDetails, total, err := l.svcCtx.AgentClosureModel.FindUnionPageListByPageWithTotal(l.ctx, agentModel.Id, req.SubordinateID, req.Page, req.PageSize)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取分页列表%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换为响应类型
|
||||||
|
detailList := make([]types.AgentSubordinateContributionDetail, 0, len(unionDetails))
|
||||||
|
for _, v := range unionDetails {
|
||||||
|
detail := types.AgentSubordinateContributionDetail{
|
||||||
|
ID: v.Id,
|
||||||
|
CreateTime: v.CreateTime,
|
||||||
|
Amount: v.Amount,
|
||||||
|
Type: v.Type,
|
||||||
|
}
|
||||||
|
detailList = append(detailList, detail)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.GetAgentSubordinateContributionDetailResp{
|
||||||
|
Mobile: maskPhone(mobile),
|
||||||
|
Total: total,
|
||||||
|
CreateTime: closure.CreateTime.Format("2006-01-02 15:04:05"),
|
||||||
|
TotalEarnings: totalEarnings,
|
||||||
|
TotalContribution: totalContribution,
|
||||||
|
TotalOrders: int64(len(commissionList)),
|
||||||
|
LevelName: subordinateAgent.LevelName,
|
||||||
|
List: detailList,
|
||||||
|
Stats: stats,
|
||||||
|
}, nil
|
||||||
|
}
|
@ -0,0 +1,173 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"qnc-server/app/user/cmd/api/internal/svc"
|
||||||
|
"qnc-server/app/user/cmd/api/internal/types"
|
||||||
|
"qnc-server/app/user/model"
|
||||||
|
"qnc-server/common/ctxdata"
|
||||||
|
"qnc-server/common/xerr"
|
||||||
|
"qnc-server/pkg/lzkit/crypto"
|
||||||
|
|
||||||
|
"github.com/Masterminds/squirrel"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"github.com/zeromicro/go-zero/core/mr"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetAgentSubordinateListLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetAgentSubordinateListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentSubordinateListLogic {
|
||||||
|
return &GetAgentSubordinateListLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetAgentSubordinateListLogic) GetAgentSubordinateList(req *types.GetAgentSubordinateListReq) (resp *types.GetAgentSubordinateListResp, err error) {
|
||||||
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理下级列表, 获取用户ID%v", err)
|
||||||
|
}
|
||||||
|
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级列表, 获取代理信息%v", err)
|
||||||
|
}
|
||||||
|
agentID := agentModel.Id
|
||||||
|
|
||||||
|
builder := l.svcCtx.AgentClosureModel.SelectBuilder().Where(squirrel.Eq{
|
||||||
|
"ancestor_id": agentID,
|
||||||
|
})
|
||||||
|
agentClosureModelList, total, err := l.svcCtx.AgentClosureModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级列表, 获取代理关系%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建ID到CreateTime的映射
|
||||||
|
createTimeMap := make(map[int64]time.Time)
|
||||||
|
descendantIDs := make([]int64, 0)
|
||||||
|
for _, v := range agentClosureModelList {
|
||||||
|
descendantIDs = append(descendantIDs, v.DescendantId)
|
||||||
|
createTimeMap[v.DescendantId] = v.CreateTime
|
||||||
|
}
|
||||||
|
|
||||||
|
// 并发查询代理信息
|
||||||
|
agentMap := make(map[int64]*model.Agent)
|
||||||
|
var descendantList []types.AgentSubordinateList
|
||||||
|
err = mr.Finish(func() error {
|
||||||
|
return mr.MapReduceVoid(func(source chan<- interface{}) {
|
||||||
|
for _, id := range descendantIDs {
|
||||||
|
source <- id
|
||||||
|
}
|
||||||
|
}, func(item interface{}, writer mr.Writer[interface{}], cancel func(error)) {
|
||||||
|
id := item.(int64)
|
||||||
|
agent, err := l.svcCtx.AgentModel.FindOne(l.ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
cancel(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writer.Write(agent)
|
||||||
|
}, func(pipe <-chan interface{}, cancel func(error)) {
|
||||||
|
for item := range pipe {
|
||||||
|
agent := item.(*model.Agent)
|
||||||
|
agentMap[agent.Id] = agent
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, func() error {
|
||||||
|
// 并发查询佣金扣除信息
|
||||||
|
deductionBuilder := l.svcCtx.AgentCommissionDeductionModel.SelectBuilder().
|
||||||
|
Where(squirrel.Eq{"agent_id": agentID}).
|
||||||
|
Where(squirrel.Eq{"deducted_agent_id": descendantIDs})
|
||||||
|
deductionList, err := l.svcCtx.AgentCommissionDeductionModel.FindAll(l.ctx, deductionBuilder, "")
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级列表, 获取代理佣金扣除信息%v", err)
|
||||||
|
}
|
||||||
|
deductionMap := make(map[int64]float64)
|
||||||
|
for _, v := range deductionList {
|
||||||
|
deductionMap[v.DeductedAgentId] += v.Amount
|
||||||
|
}
|
||||||
|
|
||||||
|
// 并发查询奖励信息
|
||||||
|
rewardsBuilder := l.svcCtx.AgentRewardsModel.SelectBuilder().
|
||||||
|
Where(squirrel.Eq{"agent_id": agentID}).
|
||||||
|
Where(squirrel.Eq{"relation_agent_id": descendantIDs})
|
||||||
|
rewardsList, err := l.svcCtx.AgentRewardsModel.FindAll(l.ctx, rewardsBuilder, "")
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级列表, 获取代理奖励信息%v", err)
|
||||||
|
}
|
||||||
|
rewardsMap := make(map[int64]float64)
|
||||||
|
for _, v := range rewardsList {
|
||||||
|
if v.RelationAgentId.Valid {
|
||||||
|
rewardsMap[v.RelationAgentId.Int64] += v.Amount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 并发查询佣金信息
|
||||||
|
commissionBuilder := l.svcCtx.AgentCommissionModel.SelectBuilder().
|
||||||
|
Where(squirrel.Eq{"agent_id": descendantIDs})
|
||||||
|
commissionList, err := l.svcCtx.AgentCommissionModel.FindAll(l.ctx, commissionBuilder, "")
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级列表, 获取代理佣金信息%v", err)
|
||||||
|
}
|
||||||
|
commissionMap := make(map[int64]float64)
|
||||||
|
orderCountMap := make(map[int64]int64)
|
||||||
|
for _, v := range commissionList {
|
||||||
|
commissionMap[v.AgentId] += v.Amount
|
||||||
|
orderCountMap[v.AgentId]++
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建返回结果
|
||||||
|
secretKey := l.svcCtx.Config.Encrypt.SecretKey
|
||||||
|
descendantList = make([]types.AgentSubordinateList, 0, len(descendantIDs))
|
||||||
|
for _, id := range descendantIDs {
|
||||||
|
agent, exists := agentMap[id]
|
||||||
|
if !exists {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
mobile, err := crypto.DecryptMobile(agent.Mobile, secretKey)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理信息, 解密手机号失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
subordinate := types.AgentSubordinateList{
|
||||||
|
ID: id,
|
||||||
|
Mobile: maskPhone(mobile),
|
||||||
|
LevelName: agent.LevelName,
|
||||||
|
CreateTime: createTimeMap[id].Format("2006-01-02 15:04:05"),
|
||||||
|
TotalContribution: deductionMap[id] + rewardsMap[id],
|
||||||
|
TotalEarnings: commissionMap[id],
|
||||||
|
TotalOrders: orderCountMap[id],
|
||||||
|
}
|
||||||
|
descendantList = append(descendantList, subordinate)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.GetAgentSubordinateListResp{
|
||||||
|
Total: total,
|
||||||
|
List: descendantList,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 手机号脱敏
|
||||||
|
func maskPhone(phone string) string {
|
||||||
|
length := len(phone)
|
||||||
|
if length < 8 {
|
||||||
|
return phone // 如果长度太短,可能不是手机号,不处理
|
||||||
|
}
|
||||||
|
// 保留前3位和后4位
|
||||||
|
return phone[:3] + strings.Repeat("*", length-7) + phone[length-4:]
|
||||||
|
}
|
@ -34,6 +34,14 @@ const (
|
|||||||
TradeStatePayError = "PAYERROR" // 支付失败(其他原因,如银行返回失败)
|
TradeStatePayError = "PAYERROR" // 支付失败(其他原因,如银行返回失败)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// InitType 初始化类型
|
||||||
|
type InitType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
InitTypePlatformCert InitType = "platform_cert" // 平台证书初始化
|
||||||
|
InitTypeWxPayPubKey InitType = "wxpay_pubkey" // 微信支付公钥初始化
|
||||||
|
)
|
||||||
|
|
||||||
type WechatPayService struct {
|
type WechatPayService struct {
|
||||||
config config.WxpayConfig
|
config config.WxpayConfig
|
||||||
wechatClient *core.Client
|
wechatClient *core.Client
|
||||||
@ -41,8 +49,21 @@ type WechatPayService struct {
|
|||||||
userAuthModel model.UserAuthModel
|
userAuthModel model.UserAuthModel
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWechatPayService 初始化微信支付服务
|
// NewWechatPayService 创建微信支付服务实例
|
||||||
func NewWechatPayService(c config.Config, userAuthModel model.UserAuthModel) *WechatPayService {
|
func NewWechatPayService(c config.Config, userAuthModel model.UserAuthModel, initType InitType) *WechatPayService {
|
||||||
|
switch initType {
|
||||||
|
case InitTypePlatformCert:
|
||||||
|
return newWechatPayServiceWithPlatformCert(c, userAuthModel)
|
||||||
|
case InitTypeWxPayPubKey:
|
||||||
|
return newWechatPayServiceWithWxPayPubKey(c, userAuthModel)
|
||||||
|
default:
|
||||||
|
logx.Errorf("不支持的初始化类型: %s", initType)
|
||||||
|
panic(fmt.Sprintf("初始化失败,服务停止: %s", initType))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newWechatPayServiceWithPlatformCert 使用平台证书初始化微信支付服务
|
||||||
|
func newWechatPayServiceWithPlatformCert(c config.Config, userAuthModel model.UserAuthModel) *WechatPayService {
|
||||||
// 从配置中加载商户信息
|
// 从配置中加载商户信息
|
||||||
mchID := c.Wxpay.MchID
|
mchID := c.Wxpay.MchID
|
||||||
mchCertificateSerialNumber := c.Wxpay.MchCertificateSerialNumber
|
mchCertificateSerialNumber := c.Wxpay.MchCertificateSerialNumber
|
||||||
@ -64,14 +85,62 @@ func NewWechatPayService(c config.Config, userAuthModel model.UserAuthModel) *We
|
|||||||
logx.Errorf("创建微信支付客户端失败: %v", err)
|
logx.Errorf("创建微信支付客户端失败: %v", err)
|
||||||
panic(fmt.Sprintf("初始化失败,服务停止: %v", err)) // 记录错误并停止程序
|
panic(fmt.Sprintf("初始化失败,服务停止: %v", err)) // 记录错误并停止程序
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在初始化时获取证书访问器并创建 notifyHandler
|
// 在初始化时获取证书访问器并创建 notifyHandler
|
||||||
certificateVisitor := downloader.MgrInstance().GetCertificateVisitor(mchID)
|
certificateVisitor := downloader.MgrInstance().GetCertificateVisitor(mchID)
|
||||||
notifyHandler, err := notify.NewRSANotifyHandler(mchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(certificateVisitor))
|
notifyHandler, err := notify.NewRSANotifyHandler(mchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(certificateVisitor))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logx.Errorf("获取证书访问器失败: %v", err)
|
logx.Errorf("获取证书访问器失败: %v", err)
|
||||||
panic(fmt.Sprintf("初始化失败,服务停止: %v", err)) // 记录错误并停止程序
|
panic(fmt.Sprintf("初始化失败,服务停止: %v", err))
|
||||||
}
|
}
|
||||||
logx.Infof("微信支付客户端初始化成功")
|
|
||||||
|
logx.Infof("微信支付客户端初始化成功(平台证书方式)")
|
||||||
|
return &WechatPayService{
|
||||||
|
config: c.Wxpay,
|
||||||
|
wechatClient: client,
|
||||||
|
notifyHandler: notifyHandler,
|
||||||
|
userAuthModel: userAuthModel,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newWechatPayServiceWithWxPayPubKey 使用微信支付公钥初始化微信支付服务
|
||||||
|
func newWechatPayServiceWithWxPayPubKey(c config.Config, userAuthModel model.UserAuthModel) *WechatPayService {
|
||||||
|
// 从配置中加载商户信息
|
||||||
|
mchID := c.Wxpay.MchID
|
||||||
|
mchCertificateSerialNumber := c.Wxpay.MchCertificateSerialNumber
|
||||||
|
mchAPIv3Key := c.Wxpay.MchApiv3Key
|
||||||
|
mchPrivateKeyPath := c.Wxpay.MchPrivateKeyPath
|
||||||
|
mchPublicKeyID := c.Wxpay.MchPublicKeyID
|
||||||
|
mchPublicKeyPath := c.Wxpay.MchPublicKeyPath
|
||||||
|
// 从文件中加载商户私钥
|
||||||
|
mchPrivateKey, err := utils.LoadPrivateKeyWithPath(mchPrivateKeyPath)
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("加载商户私钥失败: %v", err)
|
||||||
|
panic(fmt.Sprintf("初始化失败,服务停止: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从文件中加载微信支付平台证书
|
||||||
|
mchPublicKey, err := utils.LoadPublicKeyWithPath(mchPublicKeyPath)
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("加载微信支付平台证书失败: %v", err)
|
||||||
|
panic(fmt.Sprintf("初始化失败,服务停止: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用商户私钥和其他参数初始化微信支付客户端
|
||||||
|
opts := []core.ClientOption{
|
||||||
|
option.WithWechatPayPublicKeyAuthCipher(mchID, mchCertificateSerialNumber, mchPrivateKey, mchPublicKeyID, mchPublicKey),
|
||||||
|
}
|
||||||
|
client, err := core.NewClient(context.Background(), opts...)
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("创建微信支付客户端失败: %v", err)
|
||||||
|
panic(fmt.Sprintf("初始化失败,服务停止: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化 notify.Handler
|
||||||
|
notifyHandler := notify.NewNotifyHandler(
|
||||||
|
mchAPIv3Key,
|
||||||
|
verifiers.NewSHA256WithRSAPubkeyVerifier(mchPublicKeyID, *mchPublicKey))
|
||||||
|
logx.Infof("微信支付客户端初始化成功(微信支付公钥方式)")
|
||||||
return &WechatPayService{
|
return &WechatPayService{
|
||||||
config: c.Wxpay,
|
config: c.Wxpay,
|
||||||
wechatClient: client,
|
wechatClient: client,
|
||||||
|
@ -105,7 +105,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
|||||||
exampleModel := model.NewExampleModel(db, c.CacheRedis)
|
exampleModel := model.NewExampleModel(db, c.CacheRedis)
|
||||||
|
|
||||||
alipayService := service.NewAliPayService(c)
|
alipayService := service.NewAliPayService(c)
|
||||||
wechatPayService := service.NewWechatPayService(c, userAuthModel)
|
wechatPayService := service.NewWechatPayService(c, userAuthModel, service.InitTypePlatformCert)
|
||||||
applePayService := service.NewApplePayService(c)
|
applePayService := service.NewApplePayService(c)
|
||||||
apiRequestService := service.NewApiRequestService(c, westDexService, yushanService, featureModel, productFeatureModel)
|
apiRequestService := service.NewApiRequestService(c, westDexService, yushanService, featureModel, productFeatureModel)
|
||||||
verificationService := service.NewVerificationService(c, westDexService, apiRequestService)
|
verificationService := service.NewVerificationService(c, westDexService, apiRequestService)
|
||||||
|
@ -98,6 +98,42 @@ type AgentProductConfigResp struct {
|
|||||||
AgentProductConfig []AgentProductConfig
|
AgentProductConfig []AgentProductConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AgentSubordinateContributionDetail struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
CreateTime string `json:"create_time"`
|
||||||
|
Amount float64 `json:"amount"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AgentSubordinateContributionStats struct {
|
||||||
|
CostCount int64 `json:"cost_count"` // 成本扣除次数
|
||||||
|
CostAmount float64 `json:"cost_amount"` // 成本扣除总额
|
||||||
|
PricingCount int64 `json:"pricing_count"` // 定价扣除次数
|
||||||
|
PricingAmount float64 `json:"pricing_amount"` // 定价扣除总额
|
||||||
|
DescendantPromotionCount int64 `json:"descendant_promotion_count"` // 下级推广次数
|
||||||
|
DescendantPromotionAmount float64 `json:"descendant_promotion_amount"` // 下级推广总额
|
||||||
|
DescendantUpgradeVipCount int64 `json:"descendant_upgrade_vip_count"` // 下级升级VIP次数
|
||||||
|
DescendantUpgradeVipAmount float64 `json:"descendant_upgrade_vip_amount"` // 下级升级VIP总额
|
||||||
|
DescendantUpgradeSvipCount int64 `json:"descendant_upgrade_svip_count"` // 下级升级SVIP次数
|
||||||
|
DescendantUpgradeSvipAmount float64 `json:"descendant_upgrade_svip_amount"` // 下级升级SVIP总额
|
||||||
|
DescendantStayActiveCount int64 `json:"descendant_stay_active_count"` // 下级保持活跃次数
|
||||||
|
DescendantStayActiveAmount float64 `json:"descendant_stay_active_amount"` // 下级保持活跃总额
|
||||||
|
DescendantNewActiveCount int64 `json:"descendant_new_active_count"` // 下级新增活跃次数
|
||||||
|
DescendantNewActiveAmount float64 `json:"descendant_new_active_amount"` // 下级新增活跃总额
|
||||||
|
DescendantWithdrawCount int64 `json:"descendant_withdraw_count"` // 下级提现次数
|
||||||
|
DescendantWithdrawAmount float64 `json:"descendant_withdraw_amount"` // 下级提现总额
|
||||||
|
}
|
||||||
|
|
||||||
|
type AgentSubordinateList struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
CreateTime string `json:"create_time"`
|
||||||
|
LevelName string `json:"level_name"`
|
||||||
|
TotalOrders int64 `json:"total_orders"` // 总单量
|
||||||
|
TotalEarnings float64 `json:"total_earnings"` // 总金额
|
||||||
|
TotalContribution float64 `json:"total_contribution"` // 总贡献
|
||||||
|
}
|
||||||
|
|
||||||
type BindMobileReq struct {
|
type BindMobileReq struct {
|
||||||
Mobile string `json:"mobile" validate:"required,mobile"`
|
Mobile string `json:"mobile" validate:"required,mobile"`
|
||||||
Code string `json:"code" validate:"required"`
|
Code string `json:"code" validate:"required"`
|
||||||
@ -137,6 +173,34 @@ type GetAgentRevenueInfoResp struct {
|
|||||||
ActiveReward ActiveReward `json:"active_reward"` // 活跃下级奖励数据
|
ActiveReward ActiveReward `json:"active_reward"` // 活跃下级奖励数据
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GetAgentSubordinateContributionDetailReq struct {
|
||||||
|
Page int64 `form:"page"` // 页码
|
||||||
|
PageSize int64 `form:"page_size"` // 每页数据量
|
||||||
|
SubordinateID int64 `form:"subordinate_id"` // 下级ID
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetAgentSubordinateContributionDetailResp struct {
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
Total int64 `json:"total"` // 总记录数
|
||||||
|
CreateTime string `json:"create_time"`
|
||||||
|
TotalEarnings float64 `json:"total_earnings"` // 总金额
|
||||||
|
TotalContribution float64 `json:"total_contribution"` // 总贡献
|
||||||
|
TotalOrders int64 `json:"total_orders"` // 总单量
|
||||||
|
LevelName string `json:"level_name"` // 等级名称
|
||||||
|
List []AgentSubordinateContributionDetail `json:"list"` // 查询列表
|
||||||
|
Stats AgentSubordinateContributionStats `json:"stats"` // 统计数据
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetAgentSubordinateListReq struct {
|
||||||
|
Page int64 `form:"page"` // 页码
|
||||||
|
PageSize int64 `form:"page_size"` // 每页数据量
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetAgentSubordinateListResp struct {
|
||||||
|
Total int64 `json:"total"` // 总记录数
|
||||||
|
List []AgentSubordinateList `json:"list"` // 查询列表
|
||||||
|
}
|
||||||
|
|
||||||
type GetCommissionReq struct {
|
type GetCommissionReq struct {
|
||||||
Page int64 `form:"page"` // 页码
|
Page int64 `form:"page"` // 页码
|
||||||
PageSize int64 `form:"page_size"` // 每页数据量
|
PageSize int64 `form:"page_size"` // 每页数据量
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"qnc-server/common/globalkey"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/zeromicro/go-zero/core/stores/cache"
|
"github.com/zeromicro/go-zero/core/stores/cache"
|
||||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
)
|
)
|
||||||
@ -12,11 +18,20 @@ type (
|
|||||||
// and implement the added methods in customAgentClosureModel.
|
// and implement the added methods in customAgentClosureModel.
|
||||||
AgentClosureModel interface {
|
AgentClosureModel interface {
|
||||||
agentClosureModel
|
agentClosureModel
|
||||||
|
FindUnionPageListByPageWithTotal(ctx context.Context, agentId, subordinateId int64, page, pageSize int64) ([]*UnionDetail, int64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
customAgentClosureModel struct {
|
customAgentClosureModel struct {
|
||||||
*defaultAgentClosureModel
|
*defaultAgentClosureModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnionDetail 合并后的详情结构
|
||||||
|
UnionDetail struct {
|
||||||
|
Id int64 `db:"id"`
|
||||||
|
CreateTime string `db:"create_time"`
|
||||||
|
Amount float64 `db:"amount"`
|
||||||
|
Type string `db:"type"`
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewAgentClosureModel returns a model for the database table.
|
// NewAgentClosureModel returns a model for the database table.
|
||||||
@ -25,3 +40,61 @@ func NewAgentClosureModel(conn sqlx.SqlConn, c cache.CacheConf) AgentClosureMode
|
|||||||
defaultAgentClosureModel: newAgentClosureModel(conn, c),
|
defaultAgentClosureModel: newAgentClosureModel(conn, c),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindUnionPageListByPageWithTotal 获取合并后的分页列表
|
||||||
|
func (m *customAgentClosureModel) FindUnionPageListByPageWithTotal(ctx context.Context, agentId, subordinateId int64, page, pageSize int64) ([]*UnionDetail, int64, error) {
|
||||||
|
// 构建UNION ALL查询
|
||||||
|
deductionQuery := fmt.Sprintf(`
|
||||||
|
SELECT id, create_time, amount, type
|
||||||
|
FROM agent_commission_deduction
|
||||||
|
WHERE agent_id = ? AND deducted_agent_id = ? AND del_state = ?
|
||||||
|
`)
|
||||||
|
|
||||||
|
rewardsQuery := fmt.Sprintf(`
|
||||||
|
SELECT id, create_time, amount, type
|
||||||
|
FROM agent_rewards
|
||||||
|
WHERE agent_id = ? AND relation_agent_id = ? AND del_state = ?
|
||||||
|
`)
|
||||||
|
|
||||||
|
// 计算总记录数
|
||||||
|
countQuery := fmt.Sprintf(`
|
||||||
|
SELECT COUNT(*) FROM (
|
||||||
|
%s
|
||||||
|
UNION ALL
|
||||||
|
%s
|
||||||
|
) AS union_table
|
||||||
|
`, deductionQuery, rewardsQuery)
|
||||||
|
|
||||||
|
var total int64
|
||||||
|
err := m.QueryRowNoCacheCtx(ctx, &total, countQuery, agentId, subordinateId, globalkey.DelStateNo, agentId, subordinateId, globalkey.DelStateNo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, errors.Wrapf(err, "查询总记录数失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建分页查询
|
||||||
|
if page < 1 {
|
||||||
|
page = 1
|
||||||
|
}
|
||||||
|
offset := (page - 1) * pageSize
|
||||||
|
|
||||||
|
unionQuery := fmt.Sprintf(`
|
||||||
|
SELECT * FROM (
|
||||||
|
%s
|
||||||
|
UNION ALL
|
||||||
|
%s
|
||||||
|
) AS union_table
|
||||||
|
ORDER BY create_time DESC
|
||||||
|
LIMIT ? OFFSET ?
|
||||||
|
`, deductionQuery, rewardsQuery)
|
||||||
|
|
||||||
|
var resp []*UnionDetail
|
||||||
|
err = m.QueryRowsNoCacheCtx(ctx, &resp, unionQuery,
|
||||||
|
agentId, subordinateId, globalkey.DelStateNo,
|
||||||
|
agentId, subordinateId, globalkey.DelStateNo,
|
||||||
|
pageSize, offset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, errors.Wrapf(err, "查询分页数据失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, total, nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user