Compare commits
43 Commits
ed50e9b778
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 5973457bd8 | |||
| 4947679b83 | |||
| 3942553ab3 | |||
| 1e2d5b199a | |||
| 38c4f65b5d | |||
| 7805d795c3 | |||
| 5c8b99b28d | |||
| 97fa4696df | |||
| c2de066043 | |||
| 0d25783e48 | |||
| e1c5512532 | |||
| 11c1c2f930 | |||
| 67eea00b63 | |||
| 82d8915d30 | |||
| 602d5f5f71 | |||
| 67082972a9 | |||
| 018abc95d6 | |||
| 38b275d019 | |||
| 53a97aa04f | |||
| 3dcef00566 | |||
| ed8d311e02 | |||
| ec72e47695 | |||
| 9e42257e4e | |||
| 64b758a36d | |||
| ba2624e310 | |||
| 21b4069465 | |||
| 0211c67f86 | |||
| cc039fcf35 | |||
| 7d76b2e3fa | |||
| f155c64a0b | |||
| 193b47893d | |||
| 5abfd7adbd | |||
| 12659c1d14 | |||
| 1150c43219 | |||
| 8e136d3ea7 | |||
| dc24500067 | |||
| cb2474b27f | |||
| b19933fcee | |||
| 293dc46343 | |||
| d2d3e589f0 | |||
| 8e1319ac39 | |||
| 41ab1e1665 | |||
| cc1680cf01 |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -20,3 +20,11 @@ data/*
|
||||
/tmp/
|
||||
|
||||
/app/api
|
||||
|
||||
# debug binary (Delve)
|
||||
_debug_bin.*
|
||||
*.exe
|
||||
|
||||
# authorization documents (PDF files)
|
||||
app/main/api/data/authorization_docs/
|
||||
**/authorization_docs/**/*.pdf
|
||||
@@ -26,6 +26,14 @@ service main {
|
||||
@handler AdminGetAgentCommissionList
|
||||
get /agent-commission/list (AdminGetAgentCommissionListReq) returns (AdminGetAgentCommissionListResp)
|
||||
|
||||
// 代理佣金状态更新
|
||||
@handler AdminUpdateAgentCommissionStatus
|
||||
post /agent-commission/update-status (AdminUpdateAgentCommissionStatusReq) returns (AdminUpdateAgentCommissionStatusResp)
|
||||
|
||||
// 批量解冻代理佣金
|
||||
@handler AdminBatchUnfreezeAgentCommission
|
||||
post /agent-commission/batch-unfreeze (AdminBatchUnfreezeAgentCommissionReq) returns (AdminBatchUnfreezeAgentCommissionResp)
|
||||
|
||||
// 代理奖励分页查询
|
||||
@handler AdminGetAgentRewardList
|
||||
get /agent-reward/list (AdminGetAgentRewardListReq) returns (AdminGetAgentRewardListResp)
|
||||
@@ -38,6 +46,14 @@ service main {
|
||||
@handler AdminGetAgentCommissionDeductionList
|
||||
get /agent-commission-deduction/list (AdminGetAgentCommissionDeductionListReq) returns (AdminGetAgentCommissionDeductionListResp)
|
||||
|
||||
// 获取代理钱包信息
|
||||
@handler AdminGetAgentWallet
|
||||
get /wallet/:agent_id (AdminGetAgentWalletReq) returns (AdminGetAgentWalletResp)
|
||||
|
||||
// 修改代理钱包余额
|
||||
@handler AdminUpdateAgentWalletBalance
|
||||
post /wallet/update-balance (AdminUpdateAgentWalletBalanceReq) returns (AdminUpdateAgentWalletBalanceResp)
|
||||
|
||||
// 平台抽佣分页查询
|
||||
@handler AdminGetAgentPlatformDeductionList
|
||||
get /agent-platform-deduction/list (AdminGetAgentPlatformDeductionListReq) returns (AdminGetAgentPlatformDeductionListResp)
|
||||
@@ -65,7 +81,36 @@ service main {
|
||||
// 银行卡提现审核(确认/拒绝)
|
||||
@handler AdminReviewBankCardWithdrawal
|
||||
post /agent-withdrawal/bank-card/review (AdminReviewBankCardWithdrawalReq) returns (AdminReviewBankCardWithdrawalResp)
|
||||
}
|
||||
|
||||
// 获取提现统计数据
|
||||
@handler AdminGetWithdrawalStatistics
|
||||
get /agent-withdrawal/statistics (AdminGetWithdrawalStatisticsReq) returns (AdminGetWithdrawalStatisticsResp)
|
||||
|
||||
// 获取代理订单统计数据
|
||||
@handler AdminGetAgentOrderStatistics
|
||||
get /agent-order/statistics (AdminGetAgentOrderStatisticsReq) returns (AdminGetAgentOrderStatisticsResp)
|
||||
|
||||
// 获取代理统计数据
|
||||
@handler AdminGetAgentStatistics
|
||||
get /statistics (AdminGetAgentStatisticsReq) returns (AdminGetAgentStatisticsResp)
|
||||
|
||||
// 获取代理链接产品统计
|
||||
@handler AdminGetAgentLinkProductStatistics
|
||||
get /agent-link/product-statistics (AdminGetAgentLinkProductStatisticsReq) returns (AdminGetAgentLinkProductStatisticsResp)
|
||||
|
||||
// 获取系统配置
|
||||
@handler AdminGetSystemConfig
|
||||
get /system-config (AdminGetSystemConfigResp)
|
||||
|
||||
// 更新系统配置
|
||||
@handler AdminUpdateSystemConfig
|
||||
post /system-config (AdminUpdateSystemConfigReq) returns (AdminUpdateSystemConfigResp)
|
||||
|
||||
// 代理钱包流水分页查询
|
||||
@handler AdminGetAgentWalletTransactionList
|
||||
get /wallet-transaction/list (AdminGetAgentWalletTransactionListReq) returns (AdminGetAgentWalletTransactionListResp)
|
||||
|
||||
}
|
||||
|
||||
type (
|
||||
// 代理分页查询请求
|
||||
@@ -129,11 +174,14 @@ type (
|
||||
|
||||
// 代理佣金分页查询请求
|
||||
AdminGetAgentCommissionListReq {
|
||||
Page int64 `form:"page"` // 页码
|
||||
PageSize int64 `form:"pageSize"` // 每页数量
|
||||
AgentId *int64 `form:"agent_id,optional"` // 代理ID(可选)
|
||||
ProductName *string `form:"product_name,optional"` // 产品名(可选)
|
||||
Status *int64 `form:"status,optional"` // 状态(可选)
|
||||
Page int64 `form:"page"` // 页码
|
||||
PageSize int64 `form:"pageSize"` // 每页数量
|
||||
AgentId *int64 `form:"agent_id,optional"` // 代理ID(可选)
|
||||
OrderId *int64 `form:"order_id,optional"` // 订单ID(可选)
|
||||
ProductName *string `form:"product_name,optional"` // 产品名(可选)
|
||||
Status *int64 `form:"status,optional"` // 状态(可选)
|
||||
CreateTimeStart *string `form:"create_time_start,optional"` // 创建时间开始(可选)
|
||||
CreateTimeEnd *string `form:"create_time_end,optional"` // 创建时间结束(可选)
|
||||
}
|
||||
|
||||
// 代理佣金列表项
|
||||
@@ -153,6 +201,29 @@ type (
|
||||
Items []AgentCommissionListItem `json:"items"` // 列表数据
|
||||
}
|
||||
|
||||
// 代理佣金状态更新请求
|
||||
AdminUpdateAgentCommissionStatusReq {
|
||||
Id int64 `json:"id"` // 佣金记录ID
|
||||
Status int64 `json:"status"` // 状态:0-已结算,1-冻结中,2-已取消
|
||||
}
|
||||
|
||||
// 代理佣金状态更新响应
|
||||
AdminUpdateAgentCommissionStatusResp {
|
||||
Success bool `json:"success"` // 是否成功
|
||||
}
|
||||
|
||||
// 批量解冻代理佣金请求
|
||||
AdminBatchUnfreezeAgentCommissionReq {
|
||||
AgentId *int64 `json:"agent_id,optional"` // 代理ID,可选。如果不传则解冻所有冻结中的佣金
|
||||
}
|
||||
|
||||
// 批量解冻代理佣金响应
|
||||
AdminBatchUnfreezeAgentCommissionResp {
|
||||
Success bool `json:"success"` // 是否成功
|
||||
Count int64 `json:"count"` // 解冻的数量
|
||||
Amount float64 `json:"amount"` // 解冻的总金额
|
||||
}
|
||||
|
||||
// 代理奖励分页查询请求
|
||||
AdminGetAgentRewardListReq {
|
||||
Page int64 `form:"page"` // 页码
|
||||
@@ -180,11 +251,12 @@ type (
|
||||
|
||||
// 代理提现分页查询请求
|
||||
AdminGetAgentWithdrawalListReq {
|
||||
Page int64 `form:"page"` // 页码
|
||||
PageSize int64 `form:"pageSize"` // 每页数量
|
||||
AgentId *int64 `form:"agent_id,optional"` // 代理ID(可选)
|
||||
Status *int64 `form:"status,optional"` // 状态(可选)
|
||||
WithdrawNo *string `form:"withdraw_no,optional"` // 提现单号(可选)
|
||||
Page int64 `form:"page"` // 页码
|
||||
PageSize int64 `form:"pageSize"` // 每页数量
|
||||
AgentId *int64 `form:"agent_id,optional"` // 代理ID(可选)
|
||||
Status *int64 `form:"status,optional"` // 状态(可选)
|
||||
WithdrawNo *string `form:"withdraw_no,optional"` // 提现单号(可选)
|
||||
WithdrawType *int64 `form:"withdraw_type,optional"` // 提现类型(可选)1-支付宝,2-银行卡
|
||||
}
|
||||
|
||||
// 代理提现列表项
|
||||
@@ -405,4 +477,123 @@ type (
|
||||
AdminReviewBankCardWithdrawalResp {
|
||||
Success bool `json:"success"` // 是否成功
|
||||
}
|
||||
|
||||
// 获取提现统计数据请求
|
||||
AdminGetWithdrawalStatisticsReq {
|
||||
}
|
||||
|
||||
// 获取提现统计数据响应
|
||||
AdminGetWithdrawalStatisticsResp {
|
||||
TotalWithdrawalAmount float64 `json:"total_withdrawal_amount"` // 总提现金额
|
||||
TodayWithdrawalAmount float64 `json:"today_withdrawal_amount"` // 今日提现金额
|
||||
TotalActualAmount float64 `json:"total_actual_amount"` // 总实际到账金额
|
||||
TotalTaxAmount float64 `json:"total_tax_amount"` // 总扣税金额
|
||||
}
|
||||
|
||||
// 获取代理订单统计数据请求
|
||||
AdminGetAgentOrderStatisticsReq {
|
||||
}
|
||||
|
||||
// 获取代理订单统计数据响应
|
||||
AdminGetAgentOrderStatisticsResp {
|
||||
TotalAgentOrderCount int64 `json:"total_agent_order_count"` // 总代理订单数
|
||||
TodayAgentOrderCount int64 `json:"today_agent_order_count"` // 今日代理订单数
|
||||
}
|
||||
|
||||
// 获取代理统计数据请求
|
||||
AdminGetAgentStatisticsReq {
|
||||
}
|
||||
|
||||
// 获取代理统计数据响应
|
||||
AdminGetAgentStatisticsResp {
|
||||
TotalAgentCount int64 `json:"total_agent_count"` // 总代理数
|
||||
TodayAgentCount int64 `json:"today_agent_count"` // 今日新增代理数
|
||||
}
|
||||
|
||||
// 获取代理链接产品统计请求
|
||||
AdminGetAgentLinkProductStatisticsReq {
|
||||
}
|
||||
|
||||
// 代理链接产品统计列表项
|
||||
AgentLinkProductStatisticsItem {
|
||||
ProductName string `json:"product_name"` // 产品名称
|
||||
LinkCount int64 `json:"link_count"` // 推广链接数量
|
||||
}
|
||||
|
||||
// 获取代理链接产品统计响应
|
||||
AdminGetAgentLinkProductStatisticsResp {
|
||||
Items []AgentLinkProductStatisticsItem `json:"items"` // 列表数据
|
||||
}
|
||||
|
||||
// 获取代理钱包信息请求
|
||||
AdminGetAgentWalletReq {
|
||||
AgentId int64 `path:"agent_id"` // 代理ID
|
||||
}
|
||||
|
||||
// 获取代理钱包信息响应
|
||||
AdminGetAgentWalletResp {
|
||||
Balance float64 `json:"balance"` // 可用余额
|
||||
FrozenBalance float64 `json:"frozen_balance"` // 冻结余额
|
||||
TotalEarnings float64 `json:"total_earnings"` // 总收益
|
||||
}
|
||||
|
||||
// 修改代理钱包余额请求
|
||||
AdminUpdateAgentWalletBalanceReq {
|
||||
AgentId int64 `json:"agent_id"` // 代理ID
|
||||
Amount float64 `json:"amount"` // 修改金额(正数增加,负数减少)
|
||||
}
|
||||
|
||||
// 修改代理钱包余额响应
|
||||
AdminUpdateAgentWalletBalanceResp {
|
||||
Success bool `json:"success"` // 是否成功
|
||||
Balance float64 `json:"balance"` // 修改后的余额
|
||||
}
|
||||
|
||||
// 更新系统配置请求
|
||||
AdminUpdateSystemConfigReq {
|
||||
CommissionSafeMode *bool `json:"commission_safe_mode,optional"` // 佣金安全防御模式:true-冻结模式,false-直接结算模式
|
||||
}
|
||||
|
||||
// 更新系统配置响应
|
||||
AdminUpdateSystemConfigResp {
|
||||
Success bool `json:"success"` // 是否成功
|
||||
}
|
||||
|
||||
// 获取系统配置响应
|
||||
AdminGetSystemConfigResp {
|
||||
CommissionSafeMode bool `json:"commission_safe_mode"` // 佣金安全防御模式
|
||||
}
|
||||
|
||||
// 代理钱包流水分页查询请求
|
||||
AdminGetAgentWalletTransactionListReq {
|
||||
Page int64 `form:"page"` // 页码
|
||||
PageSize int64 `form:"pageSize"` // 每页数量
|
||||
AgentId int64 `form:"agent_id"` // 代理ID
|
||||
TransactionType *string `form:"transaction_type,optional"` // 交易类型(可选)
|
||||
CreateTimeStart *string `form:"create_time_start,optional"` // 创建时间开始(可选)
|
||||
CreateTimeEnd *string `form:"create_time_end,optional"` // 创建时间结束(可选)
|
||||
}
|
||||
|
||||
// 代理钱包流水列表项
|
||||
AgentWalletTransactionListItem {
|
||||
Id int64 `json:"id"` // 主键
|
||||
AgentId int64 `json:"agent_id"` // 代理ID
|
||||
TransactionType string `json:"transaction_type"` // 交易类型
|
||||
Amount float64 `json:"amount"` // 变动金额
|
||||
BalanceBefore float64 `json:"balance_before"` // 变动前余额
|
||||
BalanceAfter float64 `json:"balance_after"` // 变动后余额
|
||||
FrozenBalanceBefore float64 `json:"frozen_balance_before"` // 变动前冻结余额
|
||||
FrozenBalanceAfter float64 `json:"frozen_balance_after"` // 变动后冻结余额
|
||||
TransactionId *string `json:"transaction_id"` // 关联交易ID
|
||||
RelatedUserId *int64 `json:"related_user_id"` // 关联用户ID
|
||||
Remark *string `json:"remark"` // 备注说明
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
}
|
||||
|
||||
// 代理钱包流水分页查询响应
|
||||
AdminGetAgentWalletTransactionListResp {
|
||||
Total int64 `json:"total"` // 总数
|
||||
Items []AgentWalletTransactionListItem `json:"items"` // 列表数据
|
||||
}
|
||||
|
||||
)
|
||||
@@ -45,8 +45,9 @@ service main {
|
||||
type (
|
||||
// 创建功能请求
|
||||
AdminCreateFeatureReq {
|
||||
ApiId string `json:"api_id"` // API标识
|
||||
Name string `json:"name"` // 描述
|
||||
ApiId string `json:"api_id"` // API标识
|
||||
Name string `json:"name"` // 描述
|
||||
CostPrice float64 `json:"cost_price"` // 成本价
|
||||
}
|
||||
// 创建功能响应
|
||||
AdminCreateFeatureResp {
|
||||
@@ -54,9 +55,10 @@ type (
|
||||
}
|
||||
// 更新功能请求
|
||||
AdminUpdateFeatureReq {
|
||||
Id int64 `path:"id"` // 功能ID
|
||||
ApiId *string `json:"api_id,optional"` // API标识
|
||||
Name *string `json:"name,optional"` // 描述
|
||||
Id int64 `path:"id"` // 功能ID
|
||||
ApiId *string `json:"api_id,optional"` // API标识
|
||||
Name *string `json:"name,optional"` // 描述
|
||||
CostPrice *float64 `json:"cost_price,optional"` // 成本价
|
||||
}
|
||||
// 更新功能响应
|
||||
AdminUpdateFeatureResp {
|
||||
@@ -79,11 +81,12 @@ type (
|
||||
}
|
||||
// 功能列表项
|
||||
FeatureListItem {
|
||||
Id int64 `json:"id"` // 功能ID
|
||||
ApiId string `json:"api_id"` // API标识
|
||||
Name string `json:"name"` // 描述
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
UpdateTime string `json:"update_time"` // 更新时间
|
||||
Id int64 `json:"id"` // 功能ID
|
||||
ApiId string `json:"api_id"` // API标识
|
||||
Name string `json:"name"` // 描述
|
||||
CostPrice float64 `json:"cost_price"` // 成本价
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
UpdateTime string `json:"update_time"` // 更新时间
|
||||
}
|
||||
// 获取功能列表响应
|
||||
AdminGetFeatureListResp {
|
||||
@@ -96,11 +99,12 @@ type (
|
||||
}
|
||||
// 获取功能详情响应
|
||||
AdminGetFeatureDetailResp {
|
||||
Id int64 `json:"id"` // 功能ID
|
||||
ApiId string `json:"api_id"` // API标识
|
||||
Name string `json:"name"` // 描述
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
UpdateTime string `json:"update_time"` // 更新时间
|
||||
Id int64 `json:"id"` // 功能ID
|
||||
ApiId string `json:"api_id"` // API标识
|
||||
Name string `json:"name"` // 描述
|
||||
CostPrice float64 `json:"cost_price"` // 成本价
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
UpdateTime string `json:"update_time"` // 更新时间
|
||||
}
|
||||
// 配置功能示例数据请求
|
||||
AdminConfigFeatureExampleReq {
|
||||
|
||||
21
app/main/api/desc/admin/admin_queue.api
Normal file
21
app/main/api/desc/admin/admin_queue.api
Normal file
@@ -0,0 +1,21 @@
|
||||
syntax = "v1"
|
||||
|
||||
info(
|
||||
title: "Admin Queue管理"
|
||||
desc: "管理员队列管理接口"
|
||||
author: "team"
|
||||
version: "v1"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: api/v1
|
||||
group: admin_queue
|
||||
middleware: AdminAuthInterceptor
|
||||
)
|
||||
service main {
|
||||
|
||||
}
|
||||
@@ -39,6 +39,22 @@ service main {
|
||||
@doc "重新执行代理处理"
|
||||
@handler AdminRetryAgentProcess
|
||||
post /retry-agent-process/:id (AdminRetryAgentProcessReq) returns (AdminRetryAgentProcessResp)
|
||||
|
||||
@doc "获取退款统计数据"
|
||||
@handler AdminGetRefundStatistics
|
||||
get /refund-statistics (AdminGetRefundStatisticsReq) returns (AdminGetRefundStatisticsResp)
|
||||
|
||||
@doc "获取收入和利润统计数据"
|
||||
@handler AdminGetRevenueStatistics
|
||||
get /revenue-statistics (AdminGetRevenueStatisticsReq) returns (AdminGetRevenueStatisticsResp)
|
||||
|
||||
@doc "获取订单来源统计数据"
|
||||
@handler AdminGetOrderSourceStatistics
|
||||
get /source-statistics (AdminGetOrderSourceStatisticsReq) returns (AdminGetOrderSourceStatisticsResp)
|
||||
|
||||
@doc "获取订单统计数据"
|
||||
@handler AdminGetOrderStatistics
|
||||
get /statistics (AdminGetOrderStatisticsReq) returns (AdminGetOrderStatisticsResp)
|
||||
}
|
||||
|
||||
type (
|
||||
@@ -60,6 +76,10 @@ type (
|
||||
PayTimeEnd string `form:"pay_time_end,optional"` // 支付时间结束
|
||||
RefundTimeStart string `form:"refund_time_start,optional"` // 退款时间开始
|
||||
RefundTimeEnd string `form:"refund_time_end,optional"` // 退款时间结束
|
||||
SalesCost float64 `form:"sales_cost,optional"` // 成本价
|
||||
QueryName string `form:"query_name,optional"` // 被查询人姓名(通过 query_user_record 表追溯订单)
|
||||
QueryIdCard string `form:"query_id_card,optional"` // 被查询人身份证(通过 query_user_record 表追溯订单)
|
||||
QueryMobile string `form:"query_mobile,optional"` // 被查询人手机号(通过 query_user_record 表追溯订单)
|
||||
}
|
||||
// 列表响应
|
||||
AdminGetOrderListResp {
|
||||
@@ -75,6 +95,7 @@ type (
|
||||
PaymentPlatform string `json:"payment_platform"` // 支付方式
|
||||
PaymentScene string `json:"payment_scene"` // 支付平台
|
||||
Amount float64 `json:"amount"` // 金额
|
||||
SalesCost float64 `json:"sales_cost"` // 成本价
|
||||
Status string `json:"status"` // 支付状态:pending-待支付,paid-已支付,refunded-已退款,closed-已关闭,failed-支付失败
|
||||
QueryState string `json:"query_state"` // 查询状态:pending-待查询,success-查询成功,failed-查询失败 processing-查询中
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
@@ -83,6 +104,7 @@ type (
|
||||
IsPromotion int64 `json:"is_promotion"` // 是否推广订单:0-否,1-是
|
||||
IsAgentOrder bool `json:"is_agent_order"` // 是否是代理订单
|
||||
AgentProcessStatus string `json:"agent_process_status"` // 代理事务处理状态:not_agent-非代理订单,success-处理成功,failed-处理失败,pending-待处理
|
||||
|
||||
}
|
||||
// 详情请求
|
||||
AdminGetOrderDetailReq {
|
||||
@@ -97,6 +119,7 @@ type (
|
||||
PaymentPlatform string `json:"payment_platform"` // 支付方式
|
||||
PaymentScene string `json:"payment_scene"` // 支付平台
|
||||
Amount float64 `json:"amount"` // 金额
|
||||
SalesCost float64 `json:"sales_cost"` // 成本价
|
||||
Status string `json:"status"` // 支付状态:pending-待支付,paid-已支付,refunded-已退款,closed-已关闭,failed-支付失败
|
||||
QueryState string `json:"query_state"` // 查询状态:pending-待查询,success-查询成功,failed-查询失败 processing-查询中
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
@@ -170,4 +193,58 @@ type (
|
||||
Message string `json:"message"` // 执行结果消息
|
||||
ProcessedAt string `json:"processed_at"` // 处理时间
|
||||
}
|
||||
|
||||
// 获取退款统计数据请求
|
||||
AdminGetRefundStatisticsReq {
|
||||
}
|
||||
|
||||
// 获取退款统计数据响应
|
||||
AdminGetRefundStatisticsResp {
|
||||
TotalRefundAmount float64 `json:"total_refund_amount"` // 总退款金额
|
||||
TodayRefundAmount float64 `json:"today_refund_amount"` // 今日退款金额
|
||||
}
|
||||
|
||||
// 获取收入和利润统计数据请求
|
||||
AdminGetRevenueStatisticsReq {
|
||||
}
|
||||
|
||||
// 获取收入和利润统计数据响应
|
||||
AdminGetRevenueStatisticsResp {
|
||||
TotalRevenueAmount float64 `json:"total_revenue_amount"` // 总收入金额
|
||||
TodayRevenueAmount float64 `json:"today_revenue_amount"` // 今日收入金额
|
||||
TotalProfitAmount float64 `json:"total_profit_amount"` // 总利润金额
|
||||
TodayProfitAmount float64 `json:"today_profit_amount"` // 今日利润金额
|
||||
}
|
||||
|
||||
// 获取订单来源统计数据请求
|
||||
AdminGetOrderSourceStatisticsReq {
|
||||
}
|
||||
|
||||
// 订单来源统计项
|
||||
OrderSourceStatisticsItem {
|
||||
ProductName string `json:"product_name"` // 产品名称
|
||||
OrderCount int64 `json:"order_count"` // 订单数量
|
||||
}
|
||||
|
||||
// 获取订单来源统计数据响应
|
||||
AdminGetOrderSourceStatisticsResp {
|
||||
Items []OrderSourceStatisticsItem `json:"items"` // 订单来源统计列表
|
||||
}
|
||||
|
||||
// 获取订单统计数据请求
|
||||
AdminGetOrderStatisticsReq {
|
||||
Dimension string `form:"dimension"` // 时间维度:day-日(当月1号到今天),month-月(今年1月到当月),year-年(过去5年),all-全部(按日统计)
|
||||
}
|
||||
|
||||
// 订单统计项
|
||||
OrderStatisticsItem {
|
||||
Date string `json:"date"` // 日期
|
||||
Count int64 `json:"count"` // 订单数量
|
||||
Amount float64 `json:"amount"` // 订单金额
|
||||
}
|
||||
|
||||
// 获取订单统计数据响应
|
||||
AdminGetOrderStatisticsResp {
|
||||
Items []OrderStatisticsItem `json:"items"` // 订单统计列表
|
||||
}
|
||||
)
|
||||
@@ -61,6 +61,7 @@ type (
|
||||
Nickname string `json:"nickname"` // 昵称
|
||||
Info string `json:"info"` // 备注信息
|
||||
Inside int64 `json:"inside"` // 是否内部用户 1-是 0-否
|
||||
Disable int64 `json:"disable"` // 封禁状态 0-可用 1-禁用
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
UpdateTime string `json:"update_time"` // 更新时间
|
||||
}
|
||||
@@ -77,6 +78,7 @@ type (
|
||||
Nickname string `json:"nickname"` // 昵称
|
||||
Info string `json:"info"` // 备注信息
|
||||
Inside int64 `json:"inside"` // 是否内部用户 1-是 0-否
|
||||
Disable int64 `json:"disable"` // 封禁状态 0-可用 1-禁用
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
UpdateTime string `json:"update_time"` // 更新时间
|
||||
}
|
||||
@@ -103,6 +105,7 @@ type (
|
||||
Nickname *string `json:"nickname,optional"` // 昵称
|
||||
Info *string `json:"info,optional"` // 备注信息
|
||||
Inside *int64 `json:"inside,optional"` // 是否内部用户 1-是 0-否
|
||||
Disable *int64 `json:"disable,optional"` // 封禁状态 0-可用 1-禁用
|
||||
}
|
||||
|
||||
// 更新响应
|
||||
|
||||
@@ -326,11 +326,14 @@ type (
|
||||
SubWithdrawReward float64 `json:"sub_withdraw_reward"`
|
||||
}
|
||||
Commission {
|
||||
OrderId string `json:"order_id"` // 订单号
|
||||
ProductName string `json:"product_name"`
|
||||
Amount float64 `json:"amount"`
|
||||
CreateTime string `json:"create_time"`
|
||||
QueryParams map[string]interface{} `json:"query_params,omitempty"`
|
||||
OrderId string `json:"order_id"` // 订单号
|
||||
ProductName string `json:"product_name"`
|
||||
Amount float64 `json:"amount"` // 原始佣金金额
|
||||
RefundedAmount float64 `json:"refunded_amount"` // 已退款佣金金额
|
||||
NetAmount float64 `json:"net_amount"` // 剩余净佣金金额 = amount - refunded_amount
|
||||
Status int64 `json:"status"` // 状态:0-已结算,1-冻结中,2-已退款
|
||||
CreateTime string `json:"create_time"`
|
||||
QueryParams map[string]interface{} `json:"query_params,omitempty"`
|
||||
}
|
||||
GetCommissionReq {
|
||||
Page int64 `form:"page"` // 页码
|
||||
|
||||
@@ -47,7 +47,7 @@ type (
|
||||
PaymentReq {
|
||||
Id string `json:"id"`
|
||||
PayMethod string `json:"pay_method"`
|
||||
PayType string `json:"pay_type" validate:"required,oneof=query agent_vip"`
|
||||
PayType string `json:"pay_type" validate:"required,oneof=query agent_vip agent_upgrade"`
|
||||
}
|
||||
PaymentResp {
|
||||
PrepayData interface{} `json:"prepay_data"`
|
||||
|
||||
@@ -142,7 +142,8 @@ service main {
|
||||
type (
|
||||
sendSmsReq {
|
||||
Mobile string `json:"mobile" validate:"required,mobile"`
|
||||
ActionType string `json:"actionType" validate:"required,oneof=login register query agentApply realName bindMobile"`
|
||||
CaptchaVerifyParam string `json:"captchaVerifyParam"`
|
||||
ActionType string `json:"actionType,optional" validate:"oneof=login register query agentApply realName bindMobile"`
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -29,3 +29,4 @@ import "./admin/admin_query.api"
|
||||
import "./admin/admin_agent.api"
|
||||
import "./admin/admin_api.api"
|
||||
import "./admin/admin_role_api.api"
|
||||
import "./admin/admin_queue.api"
|
||||
|
||||
@@ -17,6 +17,12 @@ VerifyCode:
|
||||
SignName: "海南海宇大数据"
|
||||
TemplateCode: "SMS_302641455"
|
||||
ValidTime: 300
|
||||
Captcha:
|
||||
AccessKeyID: "LTAI5tKGB3TVJbMHSoZN3yr9"
|
||||
AccessKeySecret: "OCQ30GWp4yENMjmfOAaagksE18bp65"
|
||||
EndpointURL: "captcha.cn-shanghai.aliyuncs.com"
|
||||
SceneID: "wynt39to"
|
||||
EKey: ""
|
||||
Encrypt:
|
||||
SecretKey: "ff83609b2b24fc73196aac3d3dfb874f"
|
||||
WestConfig:
|
||||
@@ -41,13 +47,13 @@ Alipay:
|
||||
|
||||
Wxpay:
|
||||
AppID: "wxa581992dc74d860e"
|
||||
MchID: "1682635136"
|
||||
MchCertificateSerialNumber: "5369B8AEEBDCF7AF274510252E6A8C0659C30F61"
|
||||
MchApiv3Key: "e3ea4cf0765f1e71b01bb387dfcdbc9f"
|
||||
MchPrivateKeyPath: "etc/merchant/apiclient_key.pem"
|
||||
MchPublicKeyID: "PUB_KEY_ID_0116826351362025060900382267001601"
|
||||
MchPublicKeyPath: "etc/merchant/pub_key.pem"
|
||||
MchPlatformRAS: "1FFEC3F62E31885FAB4C91ADCB8D7557E9488781"
|
||||
MchID: "1687993434"
|
||||
MchCertificateSerialNumber: "241E4BCF5B69AAAC48451DB2C7ED794EF8B3A3D3"
|
||||
MchApiv3Key: "aB3cD5eF7gH9iJ1kL2mN4oP6qR8sT0uV"
|
||||
MchPrivateKeyPath: "etc/merchant/wxpay/1687993434_20260210_cert/apiclient_key.pem"
|
||||
MchPublicKeyID: "PUB_KEY_ID_0116879934342025120200181745004208"
|
||||
MchPublicKeyPath: "etc/merchant/wxpay/1687993434_20260210_cert/pub_key.pem"
|
||||
MchPlatformRAS: "5630D013C88EA348BF66E642B6C39AA0180D4B15"
|
||||
NotifyUrl: "https://6m4685017o.goho.co/api/v1/pay/wechat/callback"
|
||||
RefundNotifyUrl: "https://6m4685017o.goho.co/api/v1/wechat/refund_callback"
|
||||
Applepay:
|
||||
@@ -62,6 +68,7 @@ Ali:
|
||||
Code: "d55b58829efb41c8aa8e86769cba4844"
|
||||
SystemConfig:
|
||||
ThreeVerify: false
|
||||
CommissionSafeMode: false # 佣金安全防御模式:true-冻结模式,false-直接结算模式
|
||||
WechatH5:
|
||||
AppID: "wxa581992dc74d860e"
|
||||
AppSecret: "4de1fbf521712247542d49907fcd5dbf"
|
||||
@@ -82,9 +89,10 @@ TaxConfig:
|
||||
TaxRate: 0.06
|
||||
TaxExemptionAmount: 0.00
|
||||
Tianyuanapi:
|
||||
AccessID: "7f8a9b2c4d5e6f1a"
|
||||
Key: "9e4f8a1b3c6d7e2f5a8b9c0d1e4f7a2b"
|
||||
AccessID: "9e60b34eb51f3827"
|
||||
Key: "04c6b4c559be6d5ba5351c04c8713a64"
|
||||
BaseURL: "https://api.tianyuanapi.com"
|
||||
Timeout: 60
|
||||
Authorization:
|
||||
FileBaseURL: "https://www.tianyuandb.com/api/v1/auth-docs" # 授权书文件访问基础URL
|
||||
FileBaseURL: "https://www.tianyuandb.com/api/v1/auth-docs" # 授权书文件访问基础URL
|
||||
ExtensionTime: 24 # 佣金解冻延迟时间,单位:24小时
|
||||
|
||||
@@ -19,6 +19,14 @@ VerifyCode:
|
||||
SignName: "海南海宇大数据"
|
||||
TemplateCode: "SMS_302641455"
|
||||
ValidTime: 300
|
||||
|
||||
Captcha:
|
||||
AccessKeyID: "LTAI5tKGB3TVJbMHSoZN3yr9"
|
||||
AccessKeySecret: "OCQ30GWp4yENMjmfOAaagksE18bp65"
|
||||
EndpointURL: "captcha.cn-shanghai.aliyuncs.com"
|
||||
SceneID: "wynt39to"
|
||||
EKey: ""
|
||||
|
||||
Encrypt:
|
||||
SecretKey: "ff83609b2b24fc73196aac3d3dfb874f"
|
||||
WestConfig:
|
||||
@@ -42,13 +50,13 @@ Alipay:
|
||||
ReturnURL: "https://www.tianyuandb.com/payment/result"
|
||||
Wxpay:
|
||||
AppID: "wxa581992dc74d860e"
|
||||
MchID: "1682635136"
|
||||
MchCertificateSerialNumber: "5369B8AEEBDCF7AF274510252E6A8C0659C30F61"
|
||||
MchApiv3Key: "e3ea4cf0765f1e71b01bb387dfcdbc9f"
|
||||
MchPrivateKeyPath: "etc/merchant/apiclient_key.pem"
|
||||
MchPublicKeyID: "PUB_KEY_ID_0116826351362025060900382267001601"
|
||||
MchPublicKeyPath: "etc/merchant/pub_key.pem"
|
||||
MchPlatformRAS: "1FFEC3F62E31885FAB4C91ADCB8D7557E9488781"
|
||||
MchID: "1687993434"
|
||||
MchCertificateSerialNumber: "241E4BCF5B69AAAC48451DB2C7ED794EF8B3A3D3"
|
||||
MchApiv3Key: "aB3cD5eF7gH9iJ1kL2mN4oP6qR8sT0uV"
|
||||
MchPrivateKeyPath: "etc/merchant/wxpay/1687993434_20260210_cert/apiclient_key.pem"
|
||||
MchPublicKeyID: "PUB_KEY_ID_0116879934342025120200181745004208"
|
||||
MchPublicKeyPath: "etc/merchant/wxpay/1687993434_20260210_cert/pub_key.pem"
|
||||
MchPlatformRAS: "5630D013C88EA348BF66E642B6C39AA0180D4B15"
|
||||
NotifyUrl: "https://www.tianyuandb.com/api/v1/pay/wechat/callback"
|
||||
RefundNotifyUrl: "https://www.tianyuandb.com/api/v1/wechat/refund_callback"
|
||||
Applepay:
|
||||
@@ -63,6 +71,7 @@ Ali:
|
||||
Code: "d55b58829efb41c8aa8e86769cba4844"
|
||||
SystemConfig:
|
||||
ThreeVerify: true
|
||||
CommissionSafeMode: false # 佣金安全防御模式:true-冻结模式,false-直接结算模式
|
||||
WechatH5:
|
||||
AppID: "wxa581992dc74d860e"
|
||||
AppSecret: "4de1fbf521712247542d49907fcd5dbf"
|
||||
@@ -83,9 +92,10 @@ TaxConfig:
|
||||
TaxRate: 0.06
|
||||
TaxExemptionAmount: 0.00
|
||||
Tianyuanapi:
|
||||
AccessID: "7f8a9b2c4d5e6f1a"
|
||||
Key: "9e4f8a1b3c6d7e2f5a8b9c0d1e4f7a2b"
|
||||
AccessID: "9e60b34eb51f3827"
|
||||
Key: "04c6b4c559be6d5ba5351c04c8713a64"
|
||||
BaseURL: "https://api.tianyuanapi.com"
|
||||
Timeout: 60
|
||||
Authorization:
|
||||
FileBaseURL: "https://www.tianyuandb.com/api/v1/auth-docs" # 授权书文件访问基础URL
|
||||
FileBaseURL: "https://www.tianyuandb.com/api/v1/auth-docs" # 授权书文件访问基础URL
|
||||
ExtensionTime: 24 # 佣金解冻延迟时间,单位:24小时
|
||||
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDAh8YNl16EkVKW
|
||||
IHDiPyx5Zz93osD4n2E7oJXPEOSGpumhsAMjXsRd32JulYDtD/B/phA/mxQiEf84
|
||||
Um4VKC16pNAEtpEyrO7ZZRhrPk2AMck6Jm81nXLoppttuS0B3VkOE/1UuvAbIz1y
|
||||
VliRLDTiIbuSM8p1rMfpsJGo4CoLaerJgzXL6MHZA0+Fhn4PQLkLIt57jC0Jh2Dg
|
||||
ayH7Ru/wgwgq6upXb7rXj0ZzMer5kkA446mLis9P6Nz1GiTUMyUy+tnORK1EpWLg
|
||||
tUifsfXsKBLlUcOrNyG1+TyeMOuY2p592Au8J2eZbwyXKRDvK2oJzsDQW04pGyJc
|
||||
oW1vObmLAgMBAAECggEAPc0XgRNezrULSo99TNK0hv/iepeu09/tSUOh8wbcJHD9
|
||||
u94RE9B+vhdPtGmfKfmc3IzE2HYCP3GBeGXVWks8VgsDjw+/igHC5duyu/IS1Jym
|
||||
mFjwB8jTsuSQLedsEBYqWP+HqSQcoMluFv6qjWcgTpo/aI3hZmahAV2hVBEozeKR
|
||||
Va+EssjI46k894Kr6s9rb9nk8hCORuLuqDXfWJdxT+UixMeYftrgmHXk6CCUb2Ct
|
||||
EjMuxi66KyfVu9w5wS0DuE583mDIgTKmD+deJWxcVyJJMJDCULY4fotWhQb2ro9L
|
||||
qndaCgBC+sOAB/PrO31E40hZhjgdToSq5SvUWgjUCQKBgQD6/zSzEGJYzjS3544l
|
||||
PWF92WT3aFJxT3+Mgd/BrTWaY2LykbDoioM/Kp+5D1bB446k534xO6uwr3LuDCOE
|
||||
jZGy/6+HQeDHSLfDZ+LgWQdEbakbniR57HXG293x3Mp5jTlZOXc8ryGURXaCP8Sy
|
||||
xwIiZPUgpo4xA0Myt/CnjW9OhwKBgQDEXjkc4tyVTsgcVevxBjT4o3g2ihYouCdt
|
||||
ClDr6iZ8Mi5A0vCcuy1A3uI5BZnax11AIwqapgjOdWgWEtyjQJ84bhesyI7km/Ya
|
||||
AeaelsgSf+mAfFgTarWb+KpD5l0jxJAlX/1PAQU6vXuUPdA4PtBbKyUKHLY0kMXr
|
||||
wE4vbPpZ3QKBgQDGvwpFt/WICFAqR0qBJmdqNZgDaDHP03lWEwjQ3YySYZxaIw8I
|
||||
M5XVkLTE3uZ9xOiQn1WHOo6q62KAKFB/h3IVYOzmlz2bz3LjYgF+UEC26HZ9je2o
|
||||
NZrVCghmmcQiF7ePdTd7b9mRBKfgXwor3fVMstB/OCNjoAe3w3rl0dKPRQKBgQC2
|
||||
oIbvdZH/DqkPqV1o6QPk5muMFbrsHfEU+U4vSrKGOUlJIqWCrpY0ydWNgMcJcPcq
|
||||
Ciz3jUmNciXeuaYX8qbiHYnJOTGkLeShZXktrz/d7Lamt35WeJz0tTztL1caR9pj
|
||||
2DVG/8T0T3uacC6x0MGIuMSW9gMDOk3Ipy5P70OaxQKBgQDFzgdJxU9Ra6AzbyBL
|
||||
hcaKb+moNEo+peKCImwY1n3FeRM6XZ59qQaGV1lYu5KPUj9T/SVaJm6DCYFKqM0r
|
||||
T1prq2LeR69nB7Dpsr2TKp57L86DoCqbxOBnWxZ/6Em65hoRYe7CAtn3yFQGKm9T
|
||||
+EdUfn1gf7AWjQAgo3bis3TaMQ==
|
||||
-----END PRIVATE KEY-----
|
||||
@@ -0,0 +1,9 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4el5skKyhhV+lFP/lx2x
|
||||
MIQ14WFzoywBmy7Jd/UnKp5i8g85rwsFKvkMD9QqdQgoUPdnKKpvKiJeQqwUeXUC
|
||||
ogVZxedg+wCj4FuOmctHTJVwWaqZ07uom78nvDJhgRCsgWR7UBRq8v9MymbPC4p7
|
||||
IkGuq+lLkYPyJFMGpk33fAua4NkKxBseyLHbB9t3vSlUFh8x2JlIYxC531362qbS
|
||||
+L2m0B2stMyQEdYxpYCtS3nsEG+ib2Du3GiT+5pAmXxZ6DGyr4jAlAWDnljwJZEf
|
||||
xJPECXSlcAsHdI6ugkC+9DwPjLs1mrEQ/BevmTT2o0wPigCRNi9xZf178L1sptYy
|
||||
DwIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
@@ -7,16 +7,17 @@ import (
|
||||
|
||||
type Config struct {
|
||||
rest.RestConf
|
||||
DataSource string
|
||||
CacheRedis cache.CacheConf
|
||||
JwtAuth JwtAuth // JWT 鉴权相关配置
|
||||
VerifyCode VerifyCode
|
||||
Encrypt Encrypt
|
||||
Alipay AlipayConfig
|
||||
Wxpay WxpayConfig
|
||||
Applepay ApplepayConfig
|
||||
Ali AliConfig
|
||||
Tianyuanapi TianyuanapiConfig
|
||||
DataSource string
|
||||
CacheRedis cache.CacheConf
|
||||
JwtAuth JwtAuth // JWT 鉴权相关配置
|
||||
VerifyCode VerifyCode
|
||||
Captcha CaptchaConfig
|
||||
Encrypt Encrypt
|
||||
Alipay AlipayConfig
|
||||
Wxpay WxpayConfig
|
||||
Applepay ApplepayConfig
|
||||
Ali AliConfig
|
||||
Tianyuanapi TianyuanapiConfig
|
||||
SystemConfig SystemConfig
|
||||
WechatH5 WechatH5Config
|
||||
Authorization AuthorizationConfig // 授权书配置
|
||||
@@ -25,6 +26,7 @@ type Config struct {
|
||||
AdminConfig AdminConfig
|
||||
AdminPromotion AdminPromotion
|
||||
TaxConfig TaxConfig
|
||||
ExtensionTime int64
|
||||
}
|
||||
|
||||
// JwtAuth 用于 JWT 鉴权配置
|
||||
@@ -41,6 +43,14 @@ type VerifyCode struct {
|
||||
TemplateCode string
|
||||
ValidTime int
|
||||
}
|
||||
|
||||
type CaptchaConfig struct {
|
||||
AccessKeyID string
|
||||
AccessKeySecret string
|
||||
EndpointURL string
|
||||
SceneID string
|
||||
EKey string
|
||||
}
|
||||
type Encrypt struct {
|
||||
SecretKey string
|
||||
}
|
||||
@@ -91,15 +101,16 @@ type YushanConfig struct {
|
||||
Url string
|
||||
}
|
||||
type SystemConfig struct {
|
||||
ThreeVerify bool
|
||||
ThreeVerify bool // 是否开启三级实名认证
|
||||
CommissionSafeMode bool // 佣金安全防御模式:true-冻结模式(status=1,进入frozen_balance),false-直接结算(status=0,进入balance)
|
||||
}
|
||||
type WechatH5Config struct {
|
||||
AppID string
|
||||
AppSecret string
|
||||
}
|
||||
type WechatMiniConfig struct {
|
||||
AppID string
|
||||
AppSecret string
|
||||
AppID string
|
||||
AppSecret string
|
||||
}
|
||||
type QueryConfig struct {
|
||||
ShareLinkExpire int64
|
||||
@@ -126,4 +137,4 @@ type TianyuanapiConfig struct {
|
||||
|
||||
type AuthorizationConfig struct {
|
||||
FileBaseURL string // 授权书文件访问基础URL
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"tydata-server/app/main/api/internal/logic/admin_agent"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
)
|
||||
|
||||
func AdminBatchUnfreezeAgentCommissionHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.AdminBatchUnfreezeAgentCommissionReq
|
||||
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 := admin_agent.NewAdminBatchUnfreezeAgentCommissionLogic(r.Context(), svcCtx)
|
||||
resp, err := l.AdminBatchUnfreezeAgentCommission(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"tydata-server/app/main/api/internal/logic/admin_agent"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
)
|
||||
|
||||
func AdminGetAgentLinkProductStatisticsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.AdminGetAgentLinkProductStatisticsReq
|
||||
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 := admin_agent.NewAdminGetAgentLinkProductStatisticsLogic(r.Context(), svcCtx)
|
||||
resp, err := l.AdminGetAgentLinkProductStatistics(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"tydata-server/app/main/api/internal/logic/admin_agent"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
)
|
||||
|
||||
func AdminGetAgentOrderStatisticsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.AdminGetAgentOrderStatisticsReq
|
||||
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 := admin_agent.NewAdminGetAgentOrderStatisticsLogic(r.Context(), svcCtx)
|
||||
resp, err := l.AdminGetAgentOrderStatistics(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"tydata-server/app/main/api/internal/logic/admin_agent"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
)
|
||||
|
||||
func AdminGetAgentStatisticsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.AdminGetAgentStatisticsReq
|
||||
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 := admin_agent.NewAdminGetAgentStatisticsLogic(r.Context(), svcCtx)
|
||||
resp, err := l.AdminGetAgentStatistics(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"tydata-server/app/main/api/internal/logic/admin_agent"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
)
|
||||
|
||||
func AdminGetAgentWalletHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.AdminGetAgentWalletReq
|
||||
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 := admin_agent.NewAdminGetAgentWalletLogic(r.Context(), svcCtx)
|
||||
resp, err := l.AdminGetAgentWallet(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"tydata-server/app/main/api/internal/logic/admin_agent"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
)
|
||||
|
||||
func AdminGetAgentWalletTransactionListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.AdminGetAgentWalletTransactionListReq
|
||||
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 := admin_agent.NewAdminGetAgentWalletTransactionListLogic(r.Context(), svcCtx)
|
||||
resp, err := l.AdminGetAgentWalletTransactionList(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"tydata-server/app/main/api/internal/logic/admin_agent"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/common/result"
|
||||
)
|
||||
|
||||
func AdminGetSystemConfigHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
l := admin_agent.NewAdminGetSystemConfigLogic(r.Context(), svcCtx)
|
||||
resp, err := l.AdminGetSystemConfig()
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"tydata-server/app/main/api/internal/logic/admin_agent"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
)
|
||||
|
||||
func AdminGetWithdrawalStatisticsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.AdminGetWithdrawalStatisticsReq
|
||||
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 := admin_agent.NewAdminGetWithdrawalStatisticsLogic(r.Context(), svcCtx)
|
||||
resp, err := l.AdminGetWithdrawalStatistics(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"tydata-server/app/main/api/internal/logic/admin_agent"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
)
|
||||
|
||||
func AdminUpdateAgentCommissionStatusHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.AdminUpdateAgentCommissionStatusReq
|
||||
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 := admin_agent.NewAdminUpdateAgentCommissionStatusLogic(r.Context(), svcCtx)
|
||||
resp, err := l.AdminUpdateAgentCommissionStatus(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"tydata-server/app/main/api/internal/logic/admin_agent"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
)
|
||||
|
||||
func AdminUpdateAgentWalletBalanceHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.AdminUpdateAgentWalletBalanceReq
|
||||
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 := admin_agent.NewAdminUpdateAgentWalletBalanceLogic(r.Context(), svcCtx)
|
||||
resp, err := l.AdminUpdateAgentWalletBalance(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"tydata-server/app/main/api/internal/logic/admin_agent"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
)
|
||||
|
||||
func AdminUpdateSystemConfigHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.AdminUpdateSystemConfigReq
|
||||
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 := admin_agent.NewAdminUpdateSystemConfigLogic(r.Context(), svcCtx)
|
||||
resp, err := l.AdminUpdateSystemConfig(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"tydata-server/app/main/api/internal/logic/admin_order"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
)
|
||||
|
||||
func AdminGetOrderSourceStatisticsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.AdminGetOrderSourceStatisticsReq
|
||||
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 := admin_order.NewAdminGetOrderSourceStatisticsLogic(r.Context(), svcCtx)
|
||||
resp, err := l.AdminGetOrderSourceStatistics(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"tydata-server/app/main/api/internal/logic/admin_order"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
)
|
||||
|
||||
func AdminGetOrderStatisticsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.AdminGetOrderStatisticsReq
|
||||
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 := admin_order.NewAdminGetOrderStatisticsLogic(r.Context(), svcCtx)
|
||||
resp, err := l.AdminGetOrderStatistics(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"tydata-server/app/main/api/internal/logic/admin_order"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
)
|
||||
|
||||
func AdminGetRefundStatisticsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.AdminGetRefundStatisticsReq
|
||||
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 := admin_order.NewAdminGetRefundStatisticsLogic(r.Context(), svcCtx)
|
||||
resp, err := l.AdminGetRefundStatistics(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"tydata-server/app/main/api/internal/logic/admin_order"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
)
|
||||
|
||||
func AdminGetRevenueStatisticsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.AdminGetRevenueStatisticsReq
|
||||
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 := admin_order.NewAdminGetRevenueStatisticsLogic(r.Context(), svcCtx)
|
||||
resp, err := l.AdminGetRevenueStatistics(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"tydata-server/app/main/api/internal/logic/auth"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/pkg/captcha"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
@@ -23,7 +25,9 @@ func SendSmsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
result.ParamValidateErrorResult(r, w, err)
|
||||
return
|
||||
}
|
||||
l := auth.NewSendSmsLogic(r.Context(), svcCtx)
|
||||
// 将 request 注入 context,供 captcha 包判断微信等环境时跳过图形验证
|
||||
ctx := context.WithValue(r.Context(), captcha.HTTPRequestContextKey, r)
|
||||
l := auth.NewSendSmsLogic(ctx, svcCtx)
|
||||
err := l.SendSms(&req)
|
||||
result.HttpResult(r, w, nil, err)
|
||||
}
|
||||
|
||||
@@ -42,16 +42,31 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
Path: "/agent-commission-deduction/list",
|
||||
Handler: admin_agent.AdminGetAgentCommissionDeductionListHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/agent-commission/batch-unfreeze",
|
||||
Handler: admin_agent.AdminBatchUnfreezeAgentCommissionHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/agent-commission/list",
|
||||
Handler: admin_agent.AdminGetAgentCommissionListHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/agent-commission/update-status",
|
||||
Handler: admin_agent.AdminUpdateAgentCommissionStatusHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/agent-link/list",
|
||||
Handler: admin_agent.AdminGetAgentLinkListHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/agent-link/product-statistics",
|
||||
Handler: admin_agent.AdminGetAgentLinkProductStatisticsHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/agent-membership-config/list",
|
||||
@@ -67,6 +82,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
Path: "/agent-membership-recharge-order/list",
|
||||
Handler: admin_agent.AdminGetAgentMembershipRechargeOrderListHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/agent-order/statistics",
|
||||
Handler: admin_agent.AdminGetAgentOrderStatisticsHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/agent-platform-deduction/list",
|
||||
@@ -97,11 +117,46 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
Path: "/agent-withdrawal/list",
|
||||
Handler: admin_agent.AdminGetAgentWithdrawalListHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/agent-withdrawal/statistics",
|
||||
Handler: admin_agent.AdminGetWithdrawalStatisticsHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/list",
|
||||
Handler: admin_agent.AdminGetAgentListHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/statistics",
|
||||
Handler: admin_agent.AdminGetAgentStatisticsHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/system-config",
|
||||
Handler: admin_agent.AdminGetSystemConfigHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/system-config",
|
||||
Handler: admin_agent.AdminUpdateSystemConfigHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/wallet-transaction/list",
|
||||
Handler: admin_agent.AdminGetAgentWalletTransactionListHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/wallet/:agent_id",
|
||||
Handler: admin_agent.AdminGetAgentWalletHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/wallet/update-balance",
|
||||
Handler: admin_agent.AdminUpdateAgentWalletBalanceHandler(serverCtx),
|
||||
},
|
||||
}...,
|
||||
),
|
||||
rest.WithPrefix("/api/v1/admin/agent"),
|
||||
@@ -309,6 +364,12 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
Path: "/list",
|
||||
Handler: admin_order.AdminGetOrderListHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
// 获取退款统计数据
|
||||
Method: http.MethodGet,
|
||||
Path: "/refund-statistics",
|
||||
Handler: admin_order.AdminGetRefundStatisticsHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
// 订单退款
|
||||
Method: http.MethodPost,
|
||||
@@ -321,6 +382,24 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
Path: "/retry-agent-process/:id",
|
||||
Handler: admin_order.AdminRetryAgentProcessHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
// 获取收入和利润统计数据
|
||||
Method: http.MethodGet,
|
||||
Path: "/revenue-statistics",
|
||||
Handler: admin_order.AdminGetRevenueStatisticsHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
// 获取订单来源统计数据
|
||||
Method: http.MethodGet,
|
||||
Path: "/source-statistics",
|
||||
Handler: admin_order.AdminGetOrderSourceStatisticsHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
// 获取订单统计数据
|
||||
Method: http.MethodGet,
|
||||
Path: "/statistics",
|
||||
Handler: admin_order.AdminGetOrderStatisticsHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
// 更新订单
|
||||
Method: http.MethodPut,
|
||||
@@ -524,6 +603,14 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
rest.WithPrefix("/api/v1/admin/query"),
|
||||
)
|
||||
|
||||
server.AddRoutes(
|
||||
rest.WithMiddlewares(
|
||||
[]rest.Middleware{serverCtx.AdminAuthInterceptor},
|
||||
[]rest.Route{}...,
|
||||
),
|
||||
rest.WithPrefix("/api/v1"),
|
||||
)
|
||||
|
||||
server.AddRoutes(
|
||||
rest.WithMiddlewares(
|
||||
[]rest.Middleware{serverCtx.AdminAuthInterceptor},
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-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
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package admin_agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
@@ -30,19 +31,39 @@ func (l *AdminGetAgentCommissionListLogic) AdminGetAgentCommissionList(req *type
|
||||
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)
|
||||
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}), "")
|
||||
// 支持模糊匹配产品名称
|
||||
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
|
||||
}
|
||||
productIdFilter = products[0].Id
|
||||
builder = builder.Where("product_id = ?", productIdFilter)
|
||||
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")
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-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
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-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
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-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
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-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
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-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
|
||||
}
|
||||
@@ -36,6 +36,9 @@ func (l *AdminGetAgentWithdrawalListLogic) AdminGetAgentWithdrawalList(req *type
|
||||
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
|
||||
@@ -49,7 +52,7 @@ func (l *AdminGetAgentWithdrawalListLogic) AdminGetAgentWithdrawalList(req *type
|
||||
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 {
|
||||
@@ -61,7 +64,7 @@ func (l *AdminGetAgentWithdrawalListLogic) AdminGetAgentWithdrawalList(req *type
|
||||
if v.PayeeName.Valid {
|
||||
item.PayeeName = v.PayeeName.String
|
||||
}
|
||||
|
||||
|
||||
items = append(items, item)
|
||||
}
|
||||
resp = &types.AdminGetAgentWithdrawalListResp{
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-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
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-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
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package admin_agent
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-server/common/xerr"
|
||||
@@ -24,9 +25,9 @@ const (
|
||||
|
||||
// 状态常量
|
||||
const (
|
||||
StatusPending = 1 // 申请中/处理中
|
||||
StatusSuccess = 2 // 成功
|
||||
StatusFailed = 3 // 失败
|
||||
StatusPending = 1 // 申请中/处理中
|
||||
StatusSuccess = 2 // 成功
|
||||
StatusFailed = 3 // 失败
|
||||
)
|
||||
|
||||
// 提现类型常量
|
||||
@@ -80,9 +81,9 @@ func (l *AdminReviewBankCardWithdrawalLogic) AdminReviewBankCardWithdrawal(req *
|
||||
return errors.Wrapf(xerr.NewErrMsg("该提现记录已处理,无法重复操作"), "状态验证失败")
|
||||
}
|
||||
|
||||
// 验证提现类型
|
||||
if record.WithdrawType != WithdrawTypeBankCard {
|
||||
return errors.Wrapf(xerr.NewErrMsg("该记录不是银行卡提现,无法审核"), "提现类型验证失败")
|
||||
// 验证提现类型(支持银行卡和支付宝提现)
|
||||
if record.WithdrawType != WithdrawTypeBankCard && record.WithdrawType != WithdrawTypeAlipay {
|
||||
return errors.Wrapf(xerr.NewErrMsg("提现类型不正确"), "提现类型验证失败")
|
||||
}
|
||||
|
||||
if req.Action == ReviewActionApprove {
|
||||
@@ -104,6 +105,49 @@ func (l *AdminReviewBankCardWithdrawalLogic) AdminReviewBankCardWithdrawal(req *
|
||||
|
||||
// 确认提现
|
||||
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}
|
||||
@@ -117,11 +161,34 @@ func (l *AdminReviewBankCardWithdrawalLogic) approveWithdrawal(ctx context.Conte
|
||||
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 {
|
||||
@@ -163,12 +230,36 @@ func (l *AdminReviewBankCardWithdrawalLogic) rejectWithdrawal(ctx context.Contex
|
||||
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 {
|
||||
@@ -185,3 +276,173 @@ func (l *AdminReviewBankCardWithdrawalLogic) rejectWithdrawal(ctx context.Contex
|
||||
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 fmt.Sprintf("系统错误,请联系客服,错误码: %s", code)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-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
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-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
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-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
|
||||
}
|
||||
@@ -115,6 +115,7 @@ func (l *AdminGetOrderDetailLogic) AdminGetOrderDetail(req *types.AdminGetOrderD
|
||||
PaymentPlatform: order.PaymentPlatform,
|
||||
PaymentScene: order.PaymentScene,
|
||||
Amount: order.Amount,
|
||||
SalesCost: order.SalesCost,
|
||||
Status: order.Status,
|
||||
CreateTime: order.CreateTime.Format("2006-01-02 15:04:05"),
|
||||
UpdateTime: order.UpdateTime.Format("2006-01-02 15:04:05"),
|
||||
|
||||
@@ -2,6 +2,8 @@ package admin_order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
@@ -9,6 +11,7 @@ import (
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-server/common/globalkey"
|
||||
"tydata-server/common/xerr"
|
||||
"tydata-server/pkg/lzkit/crypto"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/pkg/errors"
|
||||
@@ -77,6 +80,19 @@ func (l *AdminGetOrderListLogic) AdminGetOrderList(req *types.AdminGetOrderListR
|
||||
builder = builder.Where("refund_time <= ?", req.RefundTimeEnd)
|
||||
}
|
||||
|
||||
// 按被查询人(query_user_record 表)过滤:姓名、身份证、手机号(库中为密文,需解密后匹配)
|
||||
if req.QueryName != "" || req.QueryIdCard != "" || req.QueryMobile != "" {
|
||||
orderIds, filterErr := l.filterOrderIdsByQueryUserRecord(req.QueryName, req.QueryIdCard, req.QueryMobile)
|
||||
if filterErr != nil {
|
||||
return nil, filterErr
|
||||
}
|
||||
if len(orderIds) == 0 {
|
||||
builder = builder.Where("1 = 0") // 无匹配时返回空
|
||||
} else {
|
||||
builder = builder.Where(squirrel.Eq{"id": orderIds})
|
||||
}
|
||||
}
|
||||
|
||||
// 并发获取总数和列表
|
||||
var total int64
|
||||
var orders []*model.Order
|
||||
@@ -264,6 +280,7 @@ func (l *AdminGetOrderListLogic) AdminGetOrderList(req *types.AdminGetOrderListR
|
||||
PaymentPlatform: order.PaymentPlatform,
|
||||
PaymentScene: order.PaymentScene,
|
||||
Amount: order.Amount,
|
||||
SalesCost: order.SalesCost,
|
||||
Status: order.Status,
|
||||
CreateTime: order.CreateTime.Format("2006-01-02 15:04:05"),
|
||||
QueryState: queryStateMap[order.Id],
|
||||
@@ -293,3 +310,71 @@ func (l *AdminGetOrderListLogic) AdminGetOrderList(req *types.AdminGetOrderListR
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// filterOrderIdsByQueryUserRecord 根据姓名、身份证、手机号(明文)从 query_user_record 解密后匹配,返回符合条件的 order_id 列表
|
||||
func (l *AdminGetOrderListLogic) filterOrderIdsByQueryUserRecord(queryName, queryIdCard, queryMobile string) ([]int64, error) {
|
||||
secretKey := l.svcCtx.Config.Encrypt.SecretKey
|
||||
key, keyErr := hex.DecodeString(secretKey)
|
||||
if keyErr != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "Encrypt.SecretKey 解析失败: %v", keyErr)
|
||||
}
|
||||
|
||||
qb := l.svcCtx.QueryUserRecordModel.SelectBuilder().Where("order_id > ?", 0)
|
||||
recs, err := l.svcCtx.QueryUserRecordModel.FindAll(l.ctx, qb, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询 query_user_record 失败: %v", err)
|
||||
}
|
||||
|
||||
orderIds := make([]int64, 0, len(recs))
|
||||
for _, rec := range recs {
|
||||
match := true
|
||||
|
||||
if queryName != "" {
|
||||
var decName string
|
||||
if rec.Name != "" {
|
||||
bs, e := crypto.AesEcbDecrypt(rec.Name, key)
|
||||
if e != nil {
|
||||
match = false
|
||||
} else {
|
||||
decName = string(bs)
|
||||
}
|
||||
}
|
||||
if match && !strings.Contains(decName, queryName) {
|
||||
match = false
|
||||
}
|
||||
}
|
||||
|
||||
if match && queryIdCard != "" {
|
||||
var decIdCard string
|
||||
if rec.IdCard != "" {
|
||||
var e error
|
||||
decIdCard, e = crypto.DecryptIDCard(rec.IdCard, key)
|
||||
if e != nil {
|
||||
match = false
|
||||
}
|
||||
}
|
||||
if match && decIdCard != queryIdCard {
|
||||
match = false
|
||||
}
|
||||
}
|
||||
|
||||
if match && queryMobile != "" {
|
||||
var decMobile string
|
||||
if rec.Mobile != "" {
|
||||
var e error
|
||||
decMobile, e = crypto.DecryptMobile(rec.Mobile, secretKey)
|
||||
if e != nil {
|
||||
match = false
|
||||
}
|
||||
}
|
||||
if match && decMobile != queryMobile {
|
||||
match = false
|
||||
}
|
||||
}
|
||||
|
||||
if match {
|
||||
orderIds = append(orderIds, rec.OrderId)
|
||||
}
|
||||
}
|
||||
return orderIds, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type AdminGetOrderSourceStatisticsLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAdminGetOrderSourceStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetOrderSourceStatisticsLogic {
|
||||
return &AdminGetOrderSourceStatisticsLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AdminGetOrderSourceStatisticsLogic) AdminGetOrderSourceStatistics(req *types.AdminGetOrderSourceStatisticsReq) (resp *types.AdminGetOrderSourceStatisticsResp, err error) {
|
||||
// 查询所有有产品ID的订单
|
||||
builder := l.svcCtx.OrderModel.SelectBuilder()
|
||||
builder = builder.Where("product_id IS NOT NULL")
|
||||
|
||||
// 获取所有符合条件的订单
|
||||
orders, err := l.svcCtx.OrderModel.FindAll(l.ctx, builder, "id DESC")
|
||||
if err != nil {
|
||||
logx.Errorf("查询订单列表失败: %v", err)
|
||||
return nil, fmt.Errorf("查询订单列表失败: %w", err)
|
||||
}
|
||||
|
||||
logx.Infof("获取到订单数量: %d", len(orders))
|
||||
|
||||
// 统计每个产品的订单数量
|
||||
productCountMap := make(map[int64]int64)
|
||||
for _, order := range orders {
|
||||
productCountMap[order.ProductId]++
|
||||
}
|
||||
|
||||
// 构建返回结果
|
||||
items := make([]types.OrderSourceStatisticsItem, 0, len(productCountMap))
|
||||
for productId, count := range productCountMap {
|
||||
// 获取产品信息
|
||||
product, err := l.svcCtx.ProductModel.FindOne(l.ctx, productId)
|
||||
if err != nil {
|
||||
logx.Errorf("查询产品信息失败 productId=%d, err=%v", productId, err)
|
||||
// 如果查询失败,使用默认值
|
||||
items = append(items, types.OrderSourceStatisticsItem{
|
||||
ProductName: "未知产品",
|
||||
OrderCount: count,
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
items = append(items, types.OrderSourceStatisticsItem{
|
||||
ProductName: product.ProductName,
|
||||
OrderCount: count,
|
||||
})
|
||||
}
|
||||
|
||||
// 按订单数量降序排序
|
||||
for i := 0; i < len(items)-1; i++ {
|
||||
for j := i + 1; j < len(items); j++ {
|
||||
if items[i].OrderCount < items[j].OrderCount {
|
||||
items[i], items[j] = items[j], items[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logx.Infof("查询到订单来源统计数据: %d 个产品,订单总数: %d", len(items), len(orders))
|
||||
return &types.AdminGetOrderSourceStatisticsResp{
|
||||
Items: items,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 定义结果结构体
|
||||
type OrderSourceResult struct {
|
||||
ProductName string `db:"product_name"`
|
||||
OrderCount int64 `db:"order_count"`
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type AdminGetOrderStatisticsLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAdminGetOrderStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetOrderStatisticsLogic {
|
||||
return &AdminGetOrderStatisticsLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AdminGetOrderStatisticsLogic) AdminGetOrderStatistics(req *types.AdminGetOrderStatisticsReq) (resp *types.AdminGetOrderStatisticsResp, err error) {
|
||||
// 获取当前时间
|
||||
now := time.Now()
|
||||
var startTime, endTime time.Time
|
||||
|
||||
// 根据时间维度设置时间范围和格式
|
||||
switch req.Dimension {
|
||||
case "day":
|
||||
// 日:当月1号到今天
|
||||
startTime = time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
||||
endTime = time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 999999999, now.Location())
|
||||
case "month":
|
||||
// 月:今年1月到当月
|
||||
startTime = time.Date(now.Year(), 1, 1, 0, 0, 0, 0, now.Location())
|
||||
endTime = time.Date(now.Year(), now.Month(), 1, 23, 59, 59, 999999999, now.Location()).AddDate(0, 1, -1)
|
||||
case "year":
|
||||
// 年:过去5年
|
||||
startTime = time.Date(now.Year()-5, 1, 1, 0, 0, 0, 0, now.Location())
|
||||
endTime = time.Date(now.Year(), 12, 31, 23, 59, 59, 999999999, now.Location())
|
||||
case "all":
|
||||
// 全部:所有时间,但按日统计
|
||||
startTime = time.Date(2020, 1, 1, 0, 0, 0, 0, now.Location()) // 假设从2020年开始
|
||||
endTime = now
|
||||
default:
|
||||
// 默认为日
|
||||
startTime = time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
||||
endTime = time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 999999999, now.Location())
|
||||
}
|
||||
|
||||
// 构建查询条件
|
||||
builder := l.svcCtx.OrderModel.SelectBuilder().
|
||||
Where("create_time >= ? AND create_time <= ?", startTime, endTime).
|
||||
Where("status = ?", "paid") // 只统计已支付的订单
|
||||
|
||||
// 查询所有符合条件的订单
|
||||
orders, err := l.svcCtx.OrderModel.FindAll(l.ctx, builder, "create_time ASC")
|
||||
if err != nil {
|
||||
logx.Errorf("查询订单统计数据失败: %v", err)
|
||||
return nil, fmt.Errorf("查询订单统计数据失败: %w", err)
|
||||
}
|
||||
|
||||
// 按日期分组统计
|
||||
dateMap := make(map[string]*types.OrderStatisticsItem)
|
||||
|
||||
for _, order := range orders {
|
||||
var dateKey string
|
||||
if req.Dimension == "year" {
|
||||
dateKey = order.CreateTime.Format("2006")
|
||||
} else if req.Dimension == "month" {
|
||||
dateKey = order.CreateTime.Format("2006-01")
|
||||
} else {
|
||||
dateKey = order.CreateTime.Format("2006-01-02")
|
||||
}
|
||||
|
||||
if item, exists := dateMap[dateKey]; exists {
|
||||
item.Count++
|
||||
item.Amount += order.Amount
|
||||
} else {
|
||||
dateMap[dateKey] = &types.OrderStatisticsItem{
|
||||
Date: dateKey,
|
||||
Count: 1,
|
||||
Amount: order.Amount,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 转换为切片
|
||||
items := make([]types.OrderStatisticsItem, 0, len(dateMap))
|
||||
for date := range dateMap {
|
||||
items = append(items, *dateMap[date])
|
||||
}
|
||||
|
||||
// 构建响应
|
||||
resp = &types.AdminGetOrderStatisticsResp{
|
||||
Items: items,
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type AdminGetRefundStatisticsLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAdminGetRefundStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetRefundStatisticsLogic {
|
||||
return &AdminGetRefundStatisticsLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AdminGetRefundStatisticsLogic) AdminGetRefundStatistics(req *types.AdminGetRefundStatisticsReq) (resp *types.AdminGetRefundStatisticsResp, 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.OrderModel.SelectBuilder()
|
||||
|
||||
// 查询总退款金额(status=refunded表示已退款)
|
||||
totalBuilder := builder.Where("status = ?", "refunded")
|
||||
totalRefundAmount, err := l.svcCtx.OrderModel.FindSum(l.ctx, totalBuilder, "amount")
|
||||
if err != nil {
|
||||
logx.Errorf("查询总退款金额失败: %v", err)
|
||||
return nil, fmt.Errorf("查询总退款金额失败: %w", err)
|
||||
}
|
||||
|
||||
// 查询今日退款金额(status=refunded表示已退款,且退款时间为今日)
|
||||
todayBuilder := builder.Where("status = ? AND refund_time >= ? AND refund_time < ?", "refunded", startOfDay, endOfDay)
|
||||
todayRefundAmount, err := l.svcCtx.OrderModel.FindSum(l.ctx, todayBuilder, "amount")
|
||||
if err != nil {
|
||||
logx.Errorf("查询今日退款金额失败: %v", err)
|
||||
return nil, fmt.Errorf("查询今日退款金额失败: %w", err)
|
||||
}
|
||||
|
||||
// 构建响应
|
||||
resp = &types.AdminGetRefundStatisticsResp{
|
||||
TotalRefundAmount: totalRefundAmount,
|
||||
TodayRefundAmount: todayRefundAmount,
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type AdminGetRevenueStatisticsLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAdminGetRevenueStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetRevenueStatisticsLogic {
|
||||
return &AdminGetRevenueStatisticsLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AdminGetRevenueStatisticsLogic) AdminGetRevenueStatistics(req *types.AdminGetRevenueStatisticsReq) (resp *types.AdminGetRevenueStatisticsResp, 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.OrderModel.SelectBuilder()
|
||||
|
||||
// 查询总流水收入金额(status=paid表示已支付)
|
||||
totalRevenueBuilder := builder.Where("status = ?", "paid")
|
||||
totalRevenueAmount, err := l.svcCtx.OrderModel.FindSum(l.ctx, totalRevenueBuilder, "amount")
|
||||
if err != nil {
|
||||
logx.Errorf("查询总收入金额失败: %v", err)
|
||||
return nil, fmt.Errorf("查询总收入金额失败: %w", err)
|
||||
}
|
||||
|
||||
// 查询今日流水收入金额(status=paid表示已支付,且支付时间为今日)
|
||||
todayRevenueBuilder := builder.Where("status = ? AND pay_time >= ? AND pay_time < ?", "paid", startOfDay, endOfDay)
|
||||
todayRevenueAmount, err := l.svcCtx.OrderModel.FindSum(l.ctx, todayRevenueBuilder, "amount")
|
||||
if err != nil {
|
||||
logx.Errorf("查询今日收入金额失败: %v", err)
|
||||
return nil, fmt.Errorf("查询今日收入金额失败: %w", err)
|
||||
}
|
||||
|
||||
// 查询代理订单金额总和(只查询agent_platform_deduction表,不进行联表)
|
||||
deductionAmount, err := l.svcCtx.AgentPlatformDeductionModel.FindSum(
|
||||
l.ctx,
|
||||
l.svcCtx.AgentPlatformDeductionModel.SelectBuilder(),
|
||||
"amount")
|
||||
if err != nil {
|
||||
logx.Errorf("查询代理订单金额总和失败: %v", err)
|
||||
return nil, fmt.Errorf("查询代理订单金额总和失败: %w", err)
|
||||
}
|
||||
|
||||
// 计算非代理订单金额,使用订单表作为主表,关联agent_platform_deduction表,查询没有代理记录的订单
|
||||
// 使用子查询方式避免JOIN,与order/list接口保持一致的查询风格
|
||||
nonDeductionBuilder := l.svcCtx.OrderModel.SelectBuilder().
|
||||
Where("status = ? AND id NOT IN (SELECT order_id FROM agent_platform_deduction WHERE order_id IS NOT NULL)", "paid")
|
||||
nonDeductionAmount, err := l.svcCtx.OrderModel.FindSum(
|
||||
l.ctx,
|
||||
nonDeductionBuilder,
|
||||
"amount")
|
||||
if err != nil {
|
||||
logx.Errorf("查询非代理订单金额失败: %v", err)
|
||||
return nil, fmt.Errorf("查询非代理订单金额失败: %w", err)
|
||||
}
|
||||
|
||||
// 查询订单成本总和(只查询order表,不进行联表)
|
||||
orderCostBuilder := l.svcCtx.OrderModel.SelectBuilder().
|
||||
Where("status = ? AND del_state = 0", "paid")
|
||||
orderCostAmount, err := l.svcCtx.OrderModel.FindSum(
|
||||
l.ctx,
|
||||
orderCostBuilder,
|
||||
"sales_cost")
|
||||
if err != nil {
|
||||
logx.Errorf("查询订单成本总和失败: %v", err)
|
||||
return nil, fmt.Errorf("查询订单成本总和失败: %w", err)
|
||||
}
|
||||
// 计算总利润 = 代理订单金额总和 + 非代理订单金额总和 - 订单成本总和
|
||||
// 总收入 = 代理订单金额 + 非代理订单金额
|
||||
// 总利润 = 总收入 - 所有订单成本
|
||||
totalProfitAmount := deductionAmount + nonDeductionAmount - orderCostAmount
|
||||
|
||||
// 计算今日利润 = 今日代理订单金额 + 今日非代理订单金额 - 今日订单成本总和
|
||||
|
||||
// 1. 查询今日代理订单金额
|
||||
todayDeductionBuilder := l.svcCtx.AgentPlatformDeductionModel.SelectBuilder().
|
||||
Where("create_time >= ? AND create_time < ?", startOfDay, endOfDay)
|
||||
todayDeductionAmount, err := l.svcCtx.AgentPlatformDeductionModel.FindSum(
|
||||
l.ctx,
|
||||
todayDeductionBuilder,
|
||||
"amount")
|
||||
if err != nil {
|
||||
logx.Errorf("查询今日代理订单金额失败: %v", err)
|
||||
return nil, fmt.Errorf("查询今日代理订单金额失败: %w", err)
|
||||
}
|
||||
|
||||
// 2. 查询今日非代理订单金额
|
||||
todayNonDeductionBuilder := l.svcCtx.OrderModel.SelectBuilder().
|
||||
Where("status = ? AND pay_time >= ? AND pay_time < ? AND id NOT IN (SELECT order_id FROM agent_platform_deduction WHERE order_id IS NOT NULL)",
|
||||
"paid", startOfDay, endOfDay)
|
||||
todayNonDeductionAmount, err := l.svcCtx.OrderModel.FindSum(
|
||||
l.ctx,
|
||||
todayNonDeductionBuilder,
|
||||
"amount")
|
||||
if err != nil {
|
||||
logx.Errorf("查询今日非代理订单金额失败: %v", err)
|
||||
return nil, fmt.Errorf("查询今日非代理订单金额失败: %w", err)
|
||||
}
|
||||
|
||||
// 3. 查询今日订单成本总和
|
||||
todayOrderCostBuilder := l.svcCtx.OrderModel.SelectBuilder().
|
||||
Where("status = ? AND pay_time >= ? AND pay_time < ?", "paid", startOfDay, endOfDay)
|
||||
todayOrderCostAmount, err := l.svcCtx.OrderModel.FindSum(
|
||||
l.ctx,
|
||||
todayOrderCostBuilder,
|
||||
"sales_cost")
|
||||
if err != nil {
|
||||
logx.Errorf("查询今日订单成本总和失败: %v", err)
|
||||
return nil, fmt.Errorf("查询今日订单成本总和失败: %w", err)
|
||||
}
|
||||
|
||||
// 4. 计算今日利润 = 今日代理订单金额 + 今日非代理订单金额 - 今日订单成本总和
|
||||
todayProfitAmount := todayDeductionAmount + todayNonDeductionAmount - todayOrderCostAmount
|
||||
|
||||
// 构建响应
|
||||
resp = &types.AdminGetRevenueStatisticsResp{
|
||||
TotalRevenueAmount: totalRevenueAmount,
|
||||
TodayRevenueAmount: todayRevenueAmount,
|
||||
TotalProfitAmount: totalProfitAmount,
|
||||
TodayProfitAmount: todayProfitAmount,
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
paylogic "tydata-server/app/main/api/internal/logic/pay"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/app/main/model"
|
||||
@@ -91,6 +92,10 @@ func (l *AdminRefundOrderLogic) handleAlipayRefund(order *model.Order, req *type
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 退款成功后,按本次退款金额更新代理佣金状态并扣除钱包金额
|
||||
// 注意:refundAmount 为本次实际退款金额,可以是部分退款
|
||||
_ = paylogic.HandleCommissionAndWalletDeduction(l.ctx, l.svcCtx, nil, order, req.RefundAmount)
|
||||
|
||||
return &types.AdminRefundOrderResp{
|
||||
Status: model.OrderStatusRefunded,
|
||||
RefundNo: refundNo,
|
||||
@@ -115,6 +120,7 @@ func (l *AdminRefundOrderLogic) handleWechatRefund(order *model.Order, req *type
|
||||
}
|
||||
|
||||
// 微信退款是异步的,创建pending状态的退款记录
|
||||
// 注意:代理佣金扣除将在微信退款回调成功后再执行,不在此处提前扣除
|
||||
refundNo := l.generateRefundNo(order.OrderNo)
|
||||
err = l.createRefundRecordAndUpdateOrder(order, req, refundNo, "", model.OrderStatusRefunding, model.OrderRefundStatusPending)
|
||||
if err != nil {
|
||||
|
||||
@@ -43,6 +43,7 @@ func (l *AdminGetPlatformUserDetailLogic) AdminGetPlatformUserDetail(req *types.
|
||||
Nickname: "",
|
||||
Info: user.Info,
|
||||
Inside: user.Inside,
|
||||
Disable: user.Disable,
|
||||
CreateTime: user.CreateTime.Format("2006-01-02 15:04:05"),
|
||||
UpdateTime: user.UpdateTime.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
|
||||
@@ -30,8 +30,14 @@ func NewAdminGetPlatformUserListLogic(ctx context.Context, svcCtx *svc.ServiceCo
|
||||
|
||||
func (l *AdminGetPlatformUserListLogic) AdminGetPlatformUserList(req *types.AdminGetPlatformUserListReq) (resp *types.AdminGetPlatformUserListResp, err error) {
|
||||
builder := l.svcCtx.UserModel.SelectBuilder()
|
||||
secretKey := l.svcCtx.Config.Encrypt.SecretKey
|
||||
if req.Mobile != "" {
|
||||
builder = builder.Where("mobile = ?", req.Mobile)
|
||||
// 数据库存密文,搜索时把明文手机号加密后再查询
|
||||
encryptedMobile, err := crypto.EncryptMobile(req.Mobile, secretKey)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机号加密失败: %v", err)
|
||||
}
|
||||
builder = builder.Where("mobile = ?", encryptedMobile)
|
||||
}
|
||||
if req.Nickname != "" {
|
||||
builder = builder.Where("nickname = ?", req.Nickname)
|
||||
@@ -55,7 +61,6 @@ func (l *AdminGetPlatformUserListLogic) AdminGetPlatformUserList(req *types.Admi
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询用户分页失败: %v", err)
|
||||
}
|
||||
var items []types.PlatformUserListItem
|
||||
secretKey := l.svcCtx.Config.Encrypt.SecretKey
|
||||
|
||||
for _, user := range users {
|
||||
mobile := user.Mobile
|
||||
@@ -72,6 +77,7 @@ func (l *AdminGetPlatformUserListLogic) AdminGetPlatformUserList(req *types.Admi
|
||||
Nickname: "",
|
||||
Info: user.Info,
|
||||
Inside: user.Inside,
|
||||
Disable: user.Disable,
|
||||
CreateTime: user.CreateTime.Format("2006-01-02 15:04:05"),
|
||||
UpdateTime: user.UpdateTime.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
|
||||
@@ -52,6 +52,12 @@ func (l *AdminUpdatePlatformUserLogic) AdminUpdatePlatformUser(req *types.AdminU
|
||||
}
|
||||
user.Inside = *req.Inside
|
||||
}
|
||||
if req.Disable != nil {
|
||||
if *req.Disable != 1 && *req.Disable != 0 {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "封禁状态错误: %d,0-可用 1-禁用", *req.Disable)
|
||||
}
|
||||
user.Disable = *req.Disable
|
||||
}
|
||||
if req.Password != nil {
|
||||
user.Password = sql.NullString{String: *req.Password, Valid: *req.Password != ""}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"tydata-server/app/main/api/internal/service"
|
||||
@@ -43,17 +44,20 @@ func (l *AgentRealNameLogic) AgentRealName(req *types.AgentRealNameReq) (resp *t
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "代理实名, 加密手机号失败: %v", err)
|
||||
}
|
||||
// 检查手机号是否在一分钟内已发送过验证码
|
||||
redisKey := fmt.Sprintf("%s:%s", "realName", encryptedMobile)
|
||||
cacheCode, err := l.svcCtx.Redis.Get(redisKey)
|
||||
if err != nil {
|
||||
if errors.Is(err, redis.Nil) {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "代理实名, 验证码过期: %s", encryptedMobile)
|
||||
// 开发环境下跳过验证码验证
|
||||
if os.Getenv("ENV") != "development" {
|
||||
// 检查手机号是否在一分钟内已发送过验证码
|
||||
redisKey := fmt.Sprintf("%s:%s", "realName", encryptedMobile)
|
||||
cacheCode, err := l.svcCtx.Redis.Get(redisKey)
|
||||
if err != nil {
|
||||
if errors.Is(err, redis.Nil) {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "代理实名, 验证码过期: %s", encryptedMobile)
|
||||
}
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理实名, 读取验证码redis缓存失败, mobile: %s, err: %+v", encryptedMobile, err)
|
||||
}
|
||||
if cacheCode != req.Code {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "代理实名, 验证码不正确: %s", encryptedMobile)
|
||||
}
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理实名, 读取验证码redis缓存失败, mobile: %s, err: %+v", encryptedMobile, err)
|
||||
}
|
||||
if cacheCode != req.Code {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "代理实名, 验证码不正确: %s", encryptedMobile)
|
||||
}
|
||||
agent, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||
if err != nil {
|
||||
|
||||
@@ -53,6 +53,7 @@ func (l *AgentWithdrawalLogic) AgentWithdrawal(req *types.WithdrawalReq) (*types
|
||||
var (
|
||||
outBizNo string
|
||||
withdrawRes = &types.WithdrawalResp{}
|
||||
agentID int64
|
||||
)
|
||||
var finalWithdrawAmount float64 // 实际到账金额
|
||||
// 使用事务处理核心操作
|
||||
@@ -67,6 +68,7 @@ func (l *AgentWithdrawalLogic) AgentWithdrawal(req *types.WithdrawalReq) (*types
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败: %v", err)
|
||||
}
|
||||
agentID = agentModel.Id // 保存agentId用于日志
|
||||
agentRealName, err := l.svcCtx.AgentRealNameModel.FindOneByAgentId(l.ctx, agentModel.Id)
|
||||
if err != nil {
|
||||
if errors.Is(err, model.ErrNotFound) {
|
||||
@@ -109,14 +111,14 @@ func (l *AgentWithdrawalLogic) AgentWithdrawal(req *types.WithdrawalReq) (*types
|
||||
)
|
||||
|
||||
// 统一扣税逻辑:所有提现都按6%收取税收
|
||||
exemptionAmount = 0 // 免税金额 = 0
|
||||
TaxStatus = model.TaxStatusPending // 扣税状态 = 待扣税
|
||||
taxDeductionPart = req.Amount // 应税金额 = 提现金额
|
||||
taxAmount = taxDeductionPart * taxRate // 应缴税费 = 应税金额 * 税率
|
||||
finalWithdrawAmount = req.Amount - taxAmount // 实际到账金额 = 提现金额 - 应缴税费
|
||||
exemptionAmount = 0 // 免税金额 = 0
|
||||
TaxStatus = model.TaxStatusPending // 扣税状态 = 待扣税
|
||||
taxDeductionPart = req.Amount // 应税金额 = 提现金额
|
||||
taxAmount = taxDeductionPart * taxRate // 应缴税费 = 应税金额 * 税率
|
||||
finalWithdrawAmount = req.Amount - taxAmount // 实际到账金额 = 提现金额 - 应缴税费
|
||||
|
||||
// 创建提现记录(初始状态为处理中)
|
||||
withdrawalID, err := l.createWithdrawalRecord(session, agentModel.Id, req.PayeeAccount, req.Amount, finalWithdrawAmount, taxAmount, outBizNo)
|
||||
withdrawalID, err := l.createWithdrawalRecord(session, agentModel.Id, req.PayeeAccount, req.PayeeName, req.Amount, finalWithdrawAmount, taxAmount, outBizNo)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建提现记录失败: %v", err)
|
||||
}
|
||||
@@ -146,34 +148,12 @@ func (l *AgentWithdrawalLogic) AgentWithdrawal(req *types.WithdrawalReq) (*types
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 同步调用支付宝转账
|
||||
transferResp, err := l.svcCtx.AlipayService.AliTransfer(l.ctx, req.PayeeAccount, req.PayeeName, finalWithdrawAmount, "公司提现", outBizNo)
|
||||
if err != nil {
|
||||
l.Logger.Errorf("【支付宝转账失败】outBizNo:%s error:%v", outBizNo, err)
|
||||
l.handleTransferError(outBizNo, err, "支付宝接口调用失败")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "支付宝接口调用失败: %v", err)
|
||||
}
|
||||
// 支付宝提现不再直接调用转账接口,改为先申请后审核
|
||||
// 直接返回申请中状态,等待管理员审核
|
||||
withdrawRes.Status = WithdrawStatusProcessing
|
||||
withdrawRes.FailMsg = ""
|
||||
|
||||
switch {
|
||||
case transferResp.Status == "SUCCESS":
|
||||
// 立即处理成功状态
|
||||
l.handleTransferSuccess(outBizNo, transferResp)
|
||||
withdrawRes.Status = WithdrawStatusSuccess
|
||||
case transferResp.Status == "FAIL" || transferResp.SubCode != "":
|
||||
// 处理明确失败
|
||||
errorMsg := l.mapAlipayError(transferResp.SubCode)
|
||||
l.handleTransferFailure(outBizNo, transferResp)
|
||||
withdrawRes.Status = WithdrawStatusFailed
|
||||
withdrawRes.FailMsg = errorMsg
|
||||
case transferResp.Status == "DEALING":
|
||||
// 处理中状态,启动异步轮询
|
||||
go l.startAsyncPolling(outBizNo)
|
||||
withdrawRes.Status = WithdrawStatusProcessing
|
||||
default:
|
||||
// 未知状态按失败处理
|
||||
l.handleTransferError(outBizNo, fmt.Errorf("未知状态:%s", transferResp.Status), "支付宝返回未知状态")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "支付宝接口调用失败: %v", err)
|
||||
}
|
||||
l.Logger.Infof("支付宝提现申请成功 outBizNo:%s agentId:%d amount:%f", outBizNo, agentID, req.Amount)
|
||||
return withdrawRes, nil
|
||||
}
|
||||
|
||||
@@ -213,16 +193,17 @@ func (l *AgentWithdrawalLogic) mapAlipayError(code string) string {
|
||||
if msg, ok := errorMapping[code]; ok {
|
||||
return msg
|
||||
}
|
||||
return "系统错误,请联系客服"
|
||||
return fmt.Sprintf("系统错误,请联系客服,错误码: %s", code)
|
||||
}
|
||||
|
||||
// 创建提现记录(事务内操作)
|
||||
func (l *AgentWithdrawalLogic) createWithdrawalRecord(session sqlx.Session, agentID int64, payeeAccount string, amount float64, finalWithdrawAmount float64, taxAmount float64, outBizNo string) (int64, error) {
|
||||
func (l *AgentWithdrawalLogic) createWithdrawalRecord(session sqlx.Session, agentID int64, payeeAccount string, payeeName string, amount float64, finalWithdrawAmount float64, taxAmount float64, outBizNo string) (int64, error) {
|
||||
record := &model.AgentWithdrawal{
|
||||
AgentId: agentID,
|
||||
WithdrawType: 1, // 支付宝提现
|
||||
WithdrawNo: outBizNo,
|
||||
PayeeAccount: payeeAccount,
|
||||
PayeeName: sql.NullString{String: payeeName, Valid: true}, // 设置收款人姓名
|
||||
Amount: amount,
|
||||
ActualAmount: finalWithdrawAmount,
|
||||
TaxAmount: taxAmount,
|
||||
|
||||
@@ -2,13 +2,14 @@ package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-server/common/ctxdata"
|
||||
"tydata-server/common/xerr"
|
||||
"tydata-server/pkg/lzkit/crypto"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/stores/redis"
|
||||
@@ -44,7 +45,8 @@ func (l *ApplyForAgentLogic) ApplyForAgent(req *types.AgentApplyReq) (resp *type
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "加密手机号失败: %v", err)
|
||||
}
|
||||
if req.Mobile != "18889793585" {
|
||||
// 开发环境下跳过验证码验证,或者特定手机号跳过(保留原有逻辑)
|
||||
if os.Getenv("ENV") != "development" && req.Mobile != "18889793585" {
|
||||
// 校验验证码
|
||||
redisKey := fmt.Sprintf("%s:%s", "agentApply", encryptedMobile)
|
||||
cacheCode, err := l.svcCtx.Redis.Get(redisKey)
|
||||
@@ -77,6 +79,10 @@ func (l *ApplyForAgentLogic) ApplyForAgent(req *types.AgentApplyReq) (resp *type
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "代理申请, 注册用户失败: %+v", err)
|
||||
}
|
||||
} else {
|
||||
// 被封禁用户禁止登录/申请
|
||||
if user.Disable == 1 {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.USER_DISABLED), "账号已被封禁")
|
||||
}
|
||||
if claims != nil && claims.UserType == model.UserTypeTemp {
|
||||
// 临时用户,转为正式用户
|
||||
err = l.svcCtx.UserService.TempUserBindUser(l.ctx, session, user.Id)
|
||||
|
||||
@@ -118,11 +118,11 @@ func (l *BankCardWithdrawalLogic) BankCardWithdrawal(req *types.BankCardWithdraw
|
||||
)
|
||||
|
||||
// 统一扣税逻辑:所有提现都按6%收取税收
|
||||
exemptionAmount = 0 // 免税金额 = 0
|
||||
TaxStatus = model.TaxStatusPending // 扣税状态 = 待扣税
|
||||
taxDeductionPart = req.Amount // 应税金额 = 提现金额
|
||||
taxAmount = taxDeductionPart * taxRate // 应缴税费 = 应税金额 * 税率
|
||||
finalWithdrawAmount = req.Amount - taxAmount // 实际到账金额 = 提现金额 - 应缴税费
|
||||
exemptionAmount = 0 // 免税金额 = 0
|
||||
TaxStatus = model.TaxStatusPending // 扣税状态 = 待扣税
|
||||
taxDeductionPart = req.Amount // 应税金额 = 提现金额
|
||||
taxAmount = taxDeductionPart * taxRate // 应缴税费 = 应税金额 * 税率
|
||||
finalWithdrawAmount = req.Amount - taxAmount // 实际到账金额 = 提现金额 - 应缴税费
|
||||
|
||||
// 创建提现记录(初始状态为申请中,提现类型为银行卡)
|
||||
withdrawalID, err := l.createBankCardWithdrawalRecord(session, agentModel.Id, req.BankCardNo, req.BankName, agentRealName.Name, req.Amount, finalWithdrawAmount, taxAmount, outBizNo)
|
||||
@@ -189,11 +189,36 @@ func (l *BankCardWithdrawalLogic) createBankCardWithdrawalRecord(session sqlx.Se
|
||||
|
||||
// 冻结资金(事务内操作)
|
||||
func (l *BankCardWithdrawalLogic) freezeFunds(session sqlx.Session, wallet *model.AgentWallet, amount float64) error {
|
||||
// 记录变动前的余额
|
||||
balanceBefore := wallet.Balance
|
||||
frozenBalanceBefore := wallet.FrozenBalance
|
||||
|
||||
// 更新钱包余额
|
||||
wallet.Balance -= amount
|
||||
wallet.FrozenBalance += amount
|
||||
err := l.svcCtx.AgentWalletModel.UpdateWithVersion(l.ctx, session, wallet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 记录交易流水(冻结操作)
|
||||
err = l.svcCtx.AgentService.CreateWalletTransaction(
|
||||
l.ctx,
|
||||
session,
|
||||
wallet.AgentId,
|
||||
model.WalletTransactionTypeFreeze,
|
||||
amount, // 变动金额
|
||||
balanceBefore, // 变动前余额
|
||||
wallet.Balance, // 变动后余额
|
||||
frozenBalanceBefore, // 变动前冻结余额
|
||||
wallet.FrozenBalance, // 变动后冻结余额
|
||||
"", // 关联交易ID(暂时为空,创建提现记录后可以更新)
|
||||
0, // 关联用户ID
|
||||
"提现申请冻结资金", // 备注
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,13 +2,13 @@ package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-server/common/ctxdata"
|
||||
"tydata-server/common/xerr"
|
||||
"tydata-server/pkg/lzkit/crypto"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
@@ -58,13 +58,22 @@ func (l *GetAgentCommissionLogic) GetAgentCommission(req *types.GetCommissionReq
|
||||
if copyErr != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理佣金列表, %v", err)
|
||||
}
|
||||
// 显式设置 status 字段和已退款金额
|
||||
commission.Status = agentCommissionModel.Status
|
||||
commission.RefundedAmount = agentCommissionModel.RefundedAmount
|
||||
// 计算净佣金金额(防御性处理,避免出现负数)
|
||||
netAmount := agentCommissionModel.Amount - agentCommissionModel.RefundedAmount
|
||||
if netAmount < 0 {
|
||||
netAmount = 0
|
||||
}
|
||||
commission.NetAmount = netAmount
|
||||
product, findProductErr := l.svcCtx.ProductModel.FindOne(l.ctx, agentCommissionModel.ProductId)
|
||||
if findProductErr != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理佣金列表, %v", err)
|
||||
}
|
||||
commission.CreateTime = agentCommissionModel.CreateTime.Format("2006-01-02 15:04:05")
|
||||
commission.ProductName = product.ProductName
|
||||
|
||||
|
||||
// 从 order 表获取 platform_order_id
|
||||
orderModel, findOrderErr := l.svcCtx.OrderModel.FindOne(l.ctx, agentCommissionModel.OrderId)
|
||||
if findOrderErr == nil && orderModel != nil && orderModel.PlatformOrderId.Valid {
|
||||
|
||||
@@ -2,10 +2,10 @@ package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-server/common/ctxdata"
|
||||
"tydata-server/common/xerr"
|
||||
"time"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/pkg/errors"
|
||||
@@ -126,25 +126,36 @@ func calculateDirectPushReport(commissions []*model.AgentCommission, loc *time.L
|
||||
// 转换时区
|
||||
createTime := c.CreateTime
|
||||
|
||||
// 只统计未被全部退款的佣金
|
||||
if c.Status == 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
// 统计净佣金:原始金额减去已退款金额
|
||||
netAmount := c.Amount - c.RefundedAmount
|
||||
if netAmount <= 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// 统计总量
|
||||
report.TotalCommission += c.Amount
|
||||
report.TotalCommission += netAmount
|
||||
report.TotalReport++
|
||||
|
||||
// 近24小时(滚动周期)
|
||||
if createTime.After(todayStart) {
|
||||
report.Today.Commission += c.Amount
|
||||
report.Today.Commission += netAmount
|
||||
report.Today.Report++
|
||||
}
|
||||
|
||||
// 近7天(滚动周期)
|
||||
if createTime.After(last7dStart) {
|
||||
report.Last7D.Commission += c.Amount
|
||||
report.Last7D.Commission += netAmount
|
||||
report.Last7D.Report++
|
||||
}
|
||||
|
||||
// 近30天(滚动周期)
|
||||
if createTime.After(last30dStart) {
|
||||
report.Last30D.Commission += c.Amount
|
||||
report.Last30D.Commission += netAmount
|
||||
report.Last30D.Report++
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ func (l *GetBankCardInfoLogic) GetBankCardInfo(req *types.GetBankCardInfoReq) (r
|
||||
builder := l.svcCtx.AgentWithdrawalModel.SelectBuilder()
|
||||
builder = builder.Where(squirrel.Eq{"agent_id": agentModel.Id})
|
||||
builder = builder.Where(squirrel.Eq{"withdraw_type": 2}) // 银行卡提现
|
||||
builder = builder.Where(squirrel.Eq{"status": 2}) // 成功状态
|
||||
builder = builder.Where(squirrel.Eq{"status": 2}) // 成功状态
|
||||
builder = builder.OrderBy("create_time DESC")
|
||||
builder = builder.Limit(1)
|
||||
|
||||
|
||||
@@ -2,16 +2,17 @@ package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tydata-server/common/xerr"
|
||||
"tydata-server/pkg/lzkit/crypto"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
"tydata-server/common/xerr"
|
||||
"tydata-server/pkg/lzkit/crypto"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/pkg/captcha"
|
||||
|
||||
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
|
||||
dysmsapi "github.com/alibabacloud-go/dysmsapi-20170525/v3/client"
|
||||
@@ -35,13 +36,27 @@ func NewSendSmsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SendSmsLo
|
||||
}
|
||||
|
||||
func (l *SendSmsLogic) SendSms(req *types.SendSmsReq) error {
|
||||
cfg := l.svcCtx.Config.Captcha
|
||||
if err := captcha.VerifyWithRequest(captcha.Config{
|
||||
AccessKeyID: cfg.AccessKeyID,
|
||||
AccessKeySecret: cfg.AccessKeySecret,
|
||||
EndpointURL: cfg.EndpointURL,
|
||||
SceneID: cfg.SceneID,
|
||||
}, req.CaptchaVerifyParam, l.ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
// 默认action类型:当未传入时,默认为login,便于小程序环境兼容
|
||||
action := req.ActionType
|
||||
if action == "" {
|
||||
action = "login"
|
||||
}
|
||||
secretKey := l.svcCtx.Config.Encrypt.SecretKey
|
||||
encryptedMobile, err := crypto.EncryptMobile(req.Mobile, secretKey)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "短信发送, 加密手机号失败: %v", err)
|
||||
}
|
||||
// 检查手机号是否在一分钟内已发送过验证码
|
||||
limitCodeKey := fmt.Sprintf("limit:%s:%s", req.ActionType, encryptedMobile)
|
||||
limitCodeKey := fmt.Sprintf("limit:%s:%s", action, encryptedMobile)
|
||||
exists, err := l.svcCtx.Redis.Exists(limitCodeKey)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "短信发送, 读取redis缓存失败: %s", encryptedMobile)
|
||||
@@ -62,7 +77,7 @@ func (l *SendSmsLogic) SendSms(req *types.SendSmsReq) error {
|
||||
if *smsResp.Body.Code != "OK" {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "短信发送, 阿里客户端响应失败: %s", *smsResp.Body.Message)
|
||||
}
|
||||
codeKey := fmt.Sprintf("%s:%s", req.ActionType, encryptedMobile)
|
||||
codeKey := fmt.Sprintf("%s:%s", action, encryptedMobile)
|
||||
// 将验证码保存到 Redis,设置过期时间
|
||||
err = l.svcCtx.Redis.Setex(codeKey, code, l.svcCtx.Config.VerifyCode.ValidTime) // 验证码有效期5分钟
|
||||
if err != nil {
|
||||
|
||||
@@ -93,7 +93,6 @@ func (l *AlipayCallbackLogic) handleQueryOrderPayment(w http.ResponseWriter, not
|
||||
logx.Errorf("支付宝支付回调,修改订单信息失败: %+v", updateErr)
|
||||
return nil
|
||||
}
|
||||
|
||||
if order.Status == "paid" {
|
||||
if asyncErr := l.svcCtx.AsynqService.SendQueryTask(order.Id); asyncErr != nil {
|
||||
logx.Errorf("异步任务调度失败: %v", asyncErr)
|
||||
|
||||
@@ -2,9 +2,13 @@ package pay
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/app/main/model"
|
||||
@@ -27,6 +31,7 @@ type PaymentTypeResp struct {
|
||||
amount float64
|
||||
outTradeNo string
|
||||
description string
|
||||
orderID int64 // 仅 query 类型有值;agent_vip 为 0
|
||||
}
|
||||
|
||||
func NewPaymentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PaymentLogic {
|
||||
@@ -40,9 +45,10 @@ func NewPaymentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PaymentLo
|
||||
func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp, err error) {
|
||||
var paymentTypeResp *PaymentTypeResp
|
||||
var prepayData interface{}
|
||||
|
||||
l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||
switch req.PayType {
|
||||
case "agent_vip":
|
||||
case "agent_vip", "agent_upgrade":
|
||||
paymentTypeResp, err = l.AgentVipOrderPayment(req, session)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -53,8 +59,22 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
err = errors.Wrapf(xerr.NewErrCode(xerr.REUQEST_PARAM_ERROR), "不支持的支付类型: %s", req.PayType)
|
||||
return err
|
||||
}
|
||||
|
||||
// 开发环境测试支付模式:仅当 pay_method=test 时跳过实际支付,直接返回 test_payment_success
|
||||
// 支付宝/微信在开发环境下仍走真实支付流程(跳转沙箱),支付成功后由回调更新订单
|
||||
// 注意:订单状态更新在事务外进行,避免在事务中查询不到订单的问题
|
||||
isDevTestPayment := os.Getenv("ENV") == "development" && req.PayMethod == "test"
|
||||
if isDevTestPayment && paymentTypeResp != nil && paymentTypeResp.orderID != 0 {
|
||||
prepayData = "test_payment_success"
|
||||
logx.Infof("开发环境测试支付模式:订单 %s (ID: %d) 将在事务提交后更新状态", paymentTypeResp.outTradeNo, paymentTypeResp.orderID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 仅 wechat/alipay/appleiap 调起真实支付;test 仅在上面 isDevTestPayment 分支处理
|
||||
var createOrderErr error
|
||||
if req.PayMethod == "wechat" {
|
||||
prepayData, createOrderErr = l.svcCtx.WechatPayService.CreateWechatOrder(l.ctx, paymentTypeResp.amount, paymentTypeResp.description, paymentTypeResp.outTradeNo)
|
||||
@@ -62,6 +82,13 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
|
||||
prepayData, createOrderErr = l.svcCtx.AlipayService.CreateAlipayOrder(l.ctx, paymentTypeResp.amount, paymentTypeResp.description, paymentTypeResp.outTradeNo)
|
||||
} else if req.PayMethod == "appleiap" {
|
||||
prepayData = l.svcCtx.ApplePayService.GetIappayAppID(paymentTypeResp.outTradeNo)
|
||||
} else if req.PayMethod == "test" {
|
||||
if os.Getenv("ENV") != "development" {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.REUQEST_PARAM_ERROR), "开发环境测试支付仅在开发环境可用")
|
||||
}
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.REUQEST_PARAM_ERROR), "开发环境测试支付仅支持 query 类型订单")
|
||||
} else {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.REUQEST_PARAM_ERROR), "不支持的支付方式: %s", req.PayMethod)
|
||||
}
|
||||
if createOrderErr != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 创建支付订单失败: %+v", createOrderErr)
|
||||
@@ -71,6 +98,46 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 开发环境测试支付模式:事务提交后处理订单状态更新和后续流程(仅 pay_method=test 且 query 类型 orderID>0)
|
||||
isDevTestPayment := os.Getenv("ENV") == "development" && req.PayMethod == "test"
|
||||
if isDevTestPayment && paymentTypeResp != nil && paymentTypeResp.orderID != 0 {
|
||||
go func() {
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
|
||||
finalOrderID := paymentTypeResp.orderID
|
||||
order, findOrderErr := l.svcCtx.OrderModel.FindOne(context.Background(), finalOrderID)
|
||||
if findOrderErr != nil {
|
||||
logx.Errorf("开发测试模式,查找订单失败,订单ID: %d, 错误: %v", finalOrderID, findOrderErr)
|
||||
return
|
||||
}
|
||||
order.Status = "paid"
|
||||
now := time.Now()
|
||||
order.PayTime = sql.NullTime{Time: now, Valid: true}
|
||||
|
||||
// 空报告模式:在 PaymentPlatform 标记为 "test",在 paySuccessNotify.ProcessTask 中通过
|
||||
// order.PaymentPlatform == "test" 识别(isEmptyReportMode),并生成空报告、跳过 API 调用
|
||||
isEmptyReportMode := req.PayMethod == "test"
|
||||
if isEmptyReportMode {
|
||||
order.PaymentPlatform = "test"
|
||||
logx.Infof("开发环境空报告模式:订单 %s (ID: %d) 已标记为空报告模式", paymentTypeResp.outTradeNo, finalOrderID)
|
||||
}
|
||||
updateErr := l.svcCtx.OrderModel.UpdateWithVersion(context.Background(), nil, order)
|
||||
if updateErr != nil {
|
||||
logx.Errorf("开发测试模式,更新订单状态失败,订单ID: %d, 错误: %v", finalOrderID, updateErr)
|
||||
return
|
||||
}
|
||||
|
||||
if enqErr := l.svcCtx.AsynqService.SendQueryTask(finalOrderID); enqErr != nil {
|
||||
logx.Errorf("开发测试模式,入队生成报告失败,订单ID: %d, 错误: %v", finalOrderID, enqErr)
|
||||
}
|
||||
|
||||
logx.Infof("开发测试模式,订单状态已更新为已支付并已入队生成报告,订单ID: %d", finalOrderID)
|
||||
|
||||
// 再次短暂延迟,确保订单状态更新已提交
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}()
|
||||
}
|
||||
|
||||
switch v := prepayData.(type) {
|
||||
case string:
|
||||
// 如果 prepayData 是字符串类型,直接返回
|
||||
@@ -124,6 +191,42 @@ func (l *PaymentLogic) QueryOrderPayment(req *types.PaymentReq, session sqlx.Ses
|
||||
if user.Inside == 1 {
|
||||
amount = 0.01
|
||||
}
|
||||
|
||||
// 检查72小时内身份证查询次数限制
|
||||
secretKey := l.svcCtx.Config.Encrypt.SecretKey
|
||||
key, decodeErr := hex.DecodeString(secretKey)
|
||||
if decodeErr != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取AES密钥失败: %+v", decodeErr)
|
||||
}
|
||||
// 解密缓存中的参数
|
||||
decryptedParams, decryptErr := crypto.AesDecrypt(data.Params, key)
|
||||
if decryptErr != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 解密缓存参数失败: %v", decryptErr)
|
||||
}
|
||||
var params map[string]interface{}
|
||||
if unmarshalErr := json.Unmarshal(decryptedParams, ¶ms); unmarshalErr != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 解析解密参数失败: %v", unmarshalErr)
|
||||
}
|
||||
// 获取身份证号
|
||||
idCard, ok := params["id_card"].(string)
|
||||
if !ok || idCard == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取身份证号失败")
|
||||
}
|
||||
// 加密身份证号用于查询
|
||||
encryptedIdCard, encryptErr := crypto.EncryptIDCard(idCard, key)
|
||||
if encryptErr != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 加密身份证号失败: %v", encryptErr)
|
||||
}
|
||||
// 查询72小时内的查询次数
|
||||
queryCount, countErr := l.svcCtx.QueryUserRecordModel.CountByEncryptedIdCardIn72Hours(l.ctx, encryptedIdCard)
|
||||
if countErr != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 查询记录失败: %v", countErr)
|
||||
}
|
||||
// 如果72小时内查询次数大于等于2次,禁止支付(当前这次是第3次)
|
||||
if queryCount >= 2 {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("查询受限通知:检测到您72小时内已完成2次报告查询,系统已自动暂停服务。如需紧急查询,请联系客服申请临时额度。"), "生成订单, 查询次数超限: %d", queryCount)
|
||||
}
|
||||
|
||||
var orderID int64
|
||||
order := model.Order{
|
||||
OrderNo: outTradeNo,
|
||||
@@ -144,6 +247,12 @@ func (l *PaymentLogic) QueryOrderPayment(req *types.PaymentReq, session sqlx.Ses
|
||||
}
|
||||
orderID = insertedOrderID
|
||||
|
||||
// 更新查询用户记录表的 order_id,便于通过查询信息追溯订单
|
||||
if rec, findErr := l.svcCtx.QueryUserRecordModel.FindOneByQueryNo(l.ctx, outTradeNo); findErr == nil {
|
||||
rec.OrderId = orderID
|
||||
_, _ = l.svcCtx.QueryUserRecordModel.Update(l.ctx, session, rec)
|
||||
}
|
||||
|
||||
if data.AgentIdentifier != "" {
|
||||
agent, parsingErr := l.agentParsing(data.AgentIdentifier)
|
||||
if parsingErr != nil {
|
||||
@@ -157,7 +266,7 @@ func (l *PaymentLogic) QueryOrderPayment(req *types.PaymentReq, session sqlx.Ses
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 保存代理订单失败: %+v", agentOrderInsert)
|
||||
}
|
||||
}
|
||||
return &PaymentTypeResp{amount: amount, outTradeNo: outTradeNo, description: product.ProductName}, nil
|
||||
return &PaymentTypeResp{amount: amount, outTradeNo: outTradeNo, description: product.ProductName, orderID: orderID}, nil
|
||||
}
|
||||
func (l *PaymentLogic) AgentVipOrderPayment(req *types.PaymentReq, session sqlx.Session) (resp *PaymentTypeResp, err error) {
|
||||
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
|
||||
|
||||
@@ -90,6 +90,11 @@ func (l *WechatPayCallbackLogic) handleQueryOrderPayment(w http.ResponseWriter,
|
||||
logx.Errorf("微信支付回调,更新订单失败%+v", updateErr)
|
||||
return nil
|
||||
}
|
||||
// 更新查询用户记录表的 platform_order_id
|
||||
if rec, findErr := l.svcCtx.QueryUserRecordModel.FindOneByQueryNo(l.ctx, *notification.OutTradeNo); findErr == nil {
|
||||
rec.PlatformOrderId = lzUtils.StringToNullString(*notification.TransactionId)
|
||||
_, _ = l.svcCtx.QueryUserRecordModel.Update(l.ctx, nil, rec)
|
||||
}
|
||||
|
||||
if order.Status == "paid" {
|
||||
if asyncErr := l.svcCtx.AsynqService.SendQueryTask(order.Id); asyncErr != nil {
|
||||
|
||||
@@ -10,12 +10,158 @@ import (
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-server/common/globalkey"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
)
|
||||
|
||||
// HandleCommissionAndWalletDeduction 处理退款后的佣金状态更新和钱包金额扣除
|
||||
// refundAmount 为本次实际退款金额(单位:元),从代理侧总共需要承担的金额
|
||||
// 该函数会优先冲减当前订单相关的佣金(基于 RefundedAmount),不足部分再从钱包余额/冻结余额中扣除
|
||||
func HandleCommissionAndWalletDeduction(ctx context.Context, svcCtx *svc.ServiceContext, session sqlx.Session, order *model.Order, refundAmount float64) error {
|
||||
if refundAmount <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 查询当前订单关联的所有佣金记录(包括已结算和冻结),剔除已经完全退款的
|
||||
commissionBuilder := svcCtx.AgentCommissionModel.SelectBuilder()
|
||||
commissions, commissionsErr := svcCtx.AgentCommissionModel.FindAll(ctx, commissionBuilder.Where(squirrel.And{
|
||||
squirrel.Eq{"order_id": order.Id},
|
||||
squirrel.NotEq{"status": 2}, // 排除已全部退款的佣金
|
||||
}), "")
|
||||
if commissionsErr != nil {
|
||||
logx.Errorf("查询代理佣金失败,订单ID: %d, 错误: %v", order.Id, commissionsErr)
|
||||
return nil // 返回 nil,因为佣金更新失败不应影响退款流程
|
||||
}
|
||||
|
||||
if len(commissions) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 剩余需要由佣金 + 钱包共同承担的退款金额
|
||||
remainRefundAmount := refundAmount
|
||||
|
||||
// 记录每个代理本次需要从钱包扣除的金额,避免同一代理多条佣金时重复查钱包并产生多条流水
|
||||
type walletAdjust struct {
|
||||
agentId int64
|
||||
amount float64 // 需要从该代理钱包扣除的金额(正数)
|
||||
}
|
||||
walletAdjustMap := make(map[int64]*walletAdjust)
|
||||
|
||||
// 1. 先在佣金记录上做冲减:增加 RefundedAmount,必要时将状态置为已退款
|
||||
for _, commission := range commissions {
|
||||
available := commission.Amount - commission.RefundedAmount
|
||||
if available <= 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if remainRefundAmount <= 0 {
|
||||
break
|
||||
}
|
||||
|
||||
// 当前这条佣金最多可冲减 available,本次实际冲减 currentRefund
|
||||
currentRefund := available
|
||||
if currentRefund > remainRefundAmount {
|
||||
currentRefund = remainRefundAmount
|
||||
}
|
||||
|
||||
// 更新佣金的已退款金额
|
||||
commission.RefundedAmount += currentRefund
|
||||
// 如果这条佣金已经被完全冲减,则标记为已退款
|
||||
if commission.RefundedAmount >= commission.Amount {
|
||||
commission.Status = 2
|
||||
}
|
||||
|
||||
// 更新佣金状态到数据库
|
||||
var updateCommissionErr error
|
||||
if session != nil {
|
||||
updateCommissionErr = svcCtx.AgentCommissionModel.UpdateWithVersion(ctx, session, commission)
|
||||
} else {
|
||||
updateCommissionErr = svcCtx.AgentCommissionModel.UpdateWithVersion(ctx, nil, commission)
|
||||
}
|
||||
if updateCommissionErr != nil {
|
||||
logx.Errorf("更新代理佣金状态失败,佣金ID: %d, 订单ID: %d, 错误: %v", commission.Id, order.Id, updateCommissionErr)
|
||||
continue // 如果佣金状态更新失败,就不继续计入本次冲减
|
||||
}
|
||||
|
||||
// 记录该代理需要从钱包扣除的金额(可能后续还有其他佣金叠加)
|
||||
wa, ok := walletAdjustMap[commission.AgentId]
|
||||
if !ok {
|
||||
wa = &walletAdjust{agentId: commission.AgentId}
|
||||
walletAdjustMap[commission.AgentId] = wa
|
||||
}
|
||||
wa.amount += currentRefund
|
||||
|
||||
remainRefundAmount -= currentRefund
|
||||
}
|
||||
|
||||
// 2. 再按代理维度,从钱包(冻结余额/可用余额)中扣除对应金额
|
||||
for _, wa := range walletAdjustMap {
|
||||
if wa.amount <= 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// 处理用户钱包的金额扣除
|
||||
wallet, err := svcCtx.AgentWalletModel.FindOneByAgentId(ctx, wa.agentId)
|
||||
if err != nil {
|
||||
logx.Errorf("查询代理钱包失败,代理ID: %d, 错误: %v", wa.agentId, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// 记录变动前的余额
|
||||
balanceBefore := wallet.Balance
|
||||
frozenBalanceBefore := wallet.FrozenBalance
|
||||
|
||||
// 优先从冻结余额中扣除(与原先“冻结佣金优先使用冻结余额”的设计一致)
|
||||
deduct := wa.amount
|
||||
if wallet.FrozenBalance >= deduct {
|
||||
wallet.FrozenBalance -= deduct
|
||||
} else {
|
||||
remaining := deduct - wallet.FrozenBalance
|
||||
wallet.FrozenBalance = 0
|
||||
// 可用余额可以为负数,由业务承担风险
|
||||
wallet.Balance -= remaining
|
||||
}
|
||||
|
||||
// 变动后余额和冻结余额
|
||||
balanceAfter := wallet.Balance
|
||||
frozenBalanceAfter := wallet.FrozenBalance
|
||||
// 更新钱包
|
||||
var updateWalletErr error
|
||||
if session != nil {
|
||||
updateWalletErr = svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, wallet)
|
||||
} else {
|
||||
updateWalletErr = svcCtx.AgentWalletModel.UpdateWithVersion(ctx, nil, wallet)
|
||||
}
|
||||
if updateWalletErr != nil {
|
||||
logx.Errorf("更新代理钱包失败,代理ID: %d, 错误: %v", wa.agentId, updateWalletErr)
|
||||
continue
|
||||
}
|
||||
// 创建钱包交易流水记录(退款)
|
||||
transErr := svcCtx.AgentService.CreateWalletTransaction(
|
||||
ctx,
|
||||
session,
|
||||
wa.agentId,
|
||||
model.WalletTransactionTypeRefund,
|
||||
-wa.amount*-1, // 钱包流水金额为负数
|
||||
balanceBefore,
|
||||
balanceAfter,
|
||||
frozenBalanceBefore,
|
||||
frozenBalanceAfter,
|
||||
order.OrderNo,
|
||||
0, // 这里不强绑到某一条具体佣金记录,按订单维度记录
|
||||
"订单退款,佣金已扣除",
|
||||
)
|
||||
if transErr != nil {
|
||||
logx.Errorf("创建代理钱包流水记录失败,代理ID: %d, 错误: %v", wa.agentId, transErr)
|
||||
continue
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type WechatPayRefundCallbackLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
@@ -31,7 +177,8 @@ func NewWechatPayRefundCallbackLogic(ctx context.Context, svcCtx *svc.ServiceCon
|
||||
}
|
||||
|
||||
// handleQueryOrderRefund 处理查询订单退款
|
||||
func (l *WechatPayRefundCallbackLogic) handleQueryOrderRefund(orderNo string, status refunddomestic.Status) error {
|
||||
// refundAmountYuan 表示微信本次实际退款金额(单位:元)
|
||||
func (l *WechatPayRefundCallbackLogic) handleQueryOrderRefund(orderNo string, status refunddomestic.Status, refundAmountYuan float64) error {
|
||||
order, err := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, orderNo)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "查找查询订单信息失败: %s", orderNo)
|
||||
@@ -72,6 +219,9 @@ func (l *WechatPayRefundCallbackLogic) handleQueryOrderRefund(orderNo string, st
|
||||
if err := l.svcCtx.OrderModel.UpdateWithVersion(ctx, session, order); err != nil {
|
||||
return errors.Wrapf(err, "更新查询订单状态失败: %s", orderNo)
|
||||
}
|
||||
|
||||
// 退款成功时,按本次实际退款金额更新代理佣金状态并扣除钱包金额
|
||||
_ = HandleCommissionAndWalletDeduction(ctx, l.svcCtx, session, order, refundAmountYuan)
|
||||
}
|
||||
|
||||
// 查找最新的pending状态的退款记录
|
||||
@@ -174,7 +324,7 @@ func (l *WechatPayRefundCallbackLogic) WechatPayRefundCallback(w http.ResponseWr
|
||||
var statusDetermined bool = false
|
||||
|
||||
if notification.Status != nil {
|
||||
status = *notification.Status
|
||||
status = *notification.Status
|
||||
statusDetermined = true
|
||||
} else if notification.SuccessTime != nil && !notification.SuccessTime.IsZero() {
|
||||
// 如果Status为空但SuccessTime有值,说明退款成功
|
||||
@@ -194,15 +344,22 @@ func (l *WechatPayRefundCallbackLogic) WechatPayRefundCallback(w http.ResponseWr
|
||||
|
||||
var processErr error
|
||||
|
||||
// 计算本次实际退款金额(单位:元),用于后续佣金和钱包扣减
|
||||
var refundAmountYuan float64
|
||||
if notification.Amount != nil && notification.Amount.Refund != nil {
|
||||
// 微信退款金额单位为分,这里转换为元
|
||||
refundAmountYuan = float64(*notification.Amount.Refund) / 100.0
|
||||
}
|
||||
|
||||
// 4. 根据订单号前缀处理不同类型的订单
|
||||
switch {
|
||||
case strings.HasPrefix(orderNo, "Q_"):
|
||||
processErr = l.handleQueryOrderRefund(orderNo, status)
|
||||
processErr = l.handleQueryOrderRefund(orderNo, status, refundAmountYuan)
|
||||
case strings.HasPrefix(orderNo, "A_"):
|
||||
processErr = l.handleAgentOrderRefund(orderNo, status)
|
||||
default:
|
||||
// 兼容旧订单,假设没有前缀的是查询订单
|
||||
processErr = l.handleQueryOrderRefund(orderNo, status)
|
||||
processErr = l.handleQueryOrderRefund(orderNo, status, refundAmountYuan)
|
||||
}
|
||||
|
||||
// 5. 处理错误并响应
|
||||
|
||||
@@ -2,9 +2,11 @@ package query
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
"tydata-server/app/main/api/internal/service"
|
||||
"tydata-server/app/main/model"
|
||||
@@ -38,6 +40,7 @@ func NewQueryServiceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Quer
|
||||
|
||||
func (l *QueryServiceLogic) QueryService(req *types.QueryServiceReq) (resp *types.QueryServiceResp, err error) {
|
||||
if req.AgentIdentifier != "" {
|
||||
|
||||
l.ctx = context.WithValue(l.ctx, "agentIdentifier", req.AgentIdentifier)
|
||||
} else if req.App {
|
||||
l.ctx = context.WithValue(l.ctx, "app", req.App)
|
||||
@@ -106,6 +109,7 @@ func (l *QueryServiceLogic) ProcessMarriageLogic(req *types.QueryServiceReq) (*t
|
||||
if cacheDataErr != nil {
|
||||
return nil, cacheDataErr
|
||||
}
|
||||
l.recordQueryUserRecord(params, "marriage", userID, cacheNo)
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID, model.UserTypeNormal)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
|
||||
@@ -166,7 +170,7 @@ func (l *QueryServiceLogic) ProcessHomeServiceLogic(req *types.QueryServiceReq)
|
||||
if cacheDataErr != nil {
|
||||
return nil, cacheDataErr
|
||||
}
|
||||
|
||||
l.recordQueryUserRecord(params, "homeservice", userID, cacheNo)
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID, model.UserTypeNormal)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
|
||||
@@ -227,7 +231,7 @@ func (l *QueryServiceLogic) ProcessRiskAssessmentLogic(req *types.QueryServiceRe
|
||||
if cacheDataErr != nil {
|
||||
return nil, cacheDataErr
|
||||
}
|
||||
|
||||
l.recordQueryUserRecord(params, "riskassessment", userID, cacheNo)
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID, model.UserTypeNormal)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
|
||||
@@ -261,11 +265,11 @@ func (l *QueryServiceLogic) ProcessCompanyInfoLogic(req *types.QueryServiceReq)
|
||||
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "查询服务, 参数不正确: %+v", validatorErr)
|
||||
}
|
||||
|
||||
// 校验验证码
|
||||
verifyCodeErr := l.VerifyCode(data.Mobile, data.Code)
|
||||
if verifyCodeErr != nil {
|
||||
return nil, verifyCodeErr
|
||||
}
|
||||
// 校验验证码(CompanyInfo 暂不校验)
|
||||
// verifyCodeErr := l.VerifyCode(data.Mobile, data.Code)
|
||||
// if verifyCodeErr != nil {
|
||||
// return nil, verifyCodeErr
|
||||
// }
|
||||
|
||||
// 校验三要素
|
||||
verifyErr := l.Verify(data.Name, data.IDCard, data.Mobile)
|
||||
@@ -287,7 +291,7 @@ func (l *QueryServiceLogic) ProcessCompanyInfoLogic(req *types.QueryServiceReq)
|
||||
if cacheDataErr != nil {
|
||||
return nil, cacheDataErr
|
||||
}
|
||||
|
||||
l.recordQueryUserRecord(params, "companyinfo", userID, cacheNo)
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID, model.UserTypeNormal)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
|
||||
@@ -348,7 +352,7 @@ func (l *QueryServiceLogic) ProcessRentalInfoLogic(req *types.QueryServiceReq) (
|
||||
if cacheDataErr != nil {
|
||||
return nil, cacheDataErr
|
||||
}
|
||||
|
||||
l.recordQueryUserRecord(params, "rentalinfo", userID, cacheNo)
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID, model.UserTypeNormal)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
|
||||
@@ -409,7 +413,7 @@ func (l *QueryServiceLogic) ProcessPreLoanBackgroundCheckLogic(req *types.QueryS
|
||||
if cacheDataErr != nil {
|
||||
return nil, cacheDataErr
|
||||
}
|
||||
|
||||
l.recordQueryUserRecord(params, "preloanbackgroundcheck", userID, cacheNo)
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID, model.UserTypeNormal)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
|
||||
@@ -469,7 +473,7 @@ func (l *QueryServiceLogic) ProcessBackgroundCheckLogic(req *types.QueryServiceR
|
||||
if cacheDataErr != nil {
|
||||
return nil, cacheDataErr
|
||||
}
|
||||
|
||||
l.recordQueryUserRecord(params, "backgroundcheck", userID, cacheNo)
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID, model.UserTypeNormal)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
|
||||
@@ -527,7 +531,7 @@ func (l *QueryServiceLogic) ProcessPersonalDataLogic(req *types.QueryServiceReq)
|
||||
if cacheDataErr != nil {
|
||||
return nil, cacheDataErr
|
||||
}
|
||||
|
||||
l.recordQueryUserRecord(params, "personalData", userID, cacheNo)
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID, model.UserTypeNormal)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
|
||||
@@ -558,6 +562,10 @@ func (l *QueryServiceLogic) DecryptData(data string) ([]byte, error) {
|
||||
|
||||
// 校验验证码
|
||||
func (l *QueryServiceLogic) VerifyCode(mobile string, code string) error {
|
||||
// 开发环境下跳过验证码验证
|
||||
if os.Getenv("ENV") == "development" {
|
||||
return nil
|
||||
}
|
||||
secretKey := l.svcCtx.Config.Encrypt.SecretKey
|
||||
encryptedMobile, err := crypto.EncryptMobile(mobile, secretKey)
|
||||
if err != nil {
|
||||
@@ -579,6 +587,12 @@ func (l *QueryServiceLogic) VerifyCode(mobile string, code string) error {
|
||||
|
||||
// 二、三要素验证
|
||||
func (l *QueryServiceLogic) Verify(Name string, IDCard string, Mobile string) error {
|
||||
// 开发环境下跳过二/三要素验证(避免未授权IP调用天元API失败)
|
||||
isDevelopment := os.Getenv("ENV") == "development"
|
||||
if isDevelopment {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !l.svcCtx.Config.SystemConfig.ThreeVerify {
|
||||
twoVerification := service.TwoFactorVerificationRequest{
|
||||
Name: Name,
|
||||
@@ -643,6 +657,76 @@ func (l *QueryServiceLogic) CacheData(params map[string]interface{}, Product str
|
||||
return outTradeNo, nil
|
||||
}
|
||||
|
||||
// recordQueryUserRecord 写入查询用户记录表,用于通过姓名/身份证/手机号追溯订单
|
||||
// 重要:name、id_card、mobile 必须以 AES-ECB+Base64 密文入库,禁止写入明文
|
||||
func (l *QueryServiceLogic) recordQueryUserRecord(params map[string]interface{}, product string, userID int64, queryNo string) {
|
||||
getStr := func(k string) string {
|
||||
if v, ok := params[k]; ok {
|
||||
if s, ok := v.(string); ok {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
secretKey := l.svcCtx.Config.Encrypt.SecretKey
|
||||
if secretKey == "" {
|
||||
l.Errorf("查询用户记录表加密失败, Encrypt.SecretKey 未配置,拒绝写入明文 queryNo=%s", queryNo)
|
||||
return
|
||||
}
|
||||
key, keyErr := hex.DecodeString(secretKey)
|
||||
if keyErr != nil {
|
||||
l.Errorf("查询用户记录表加密失败, 密钥解析错误 queryNo=%s err=%v", queryNo, keyErr)
|
||||
return
|
||||
}
|
||||
// 以下三字段仅使用加密后的值赋值,不得使用 getStr 的明文
|
||||
encName := ""
|
||||
if name := getStr("name"); name != "" {
|
||||
if s, err := crypto.AesEcbEncrypt([]byte(name), key); err != nil {
|
||||
l.Errorf("查询用户记录表姓名加密失败 queryNo=%s err=%v", queryNo, err)
|
||||
return
|
||||
} else {
|
||||
encName = s
|
||||
}
|
||||
}
|
||||
encIdCard := ""
|
||||
if idCard := getStr("id_card"); idCard != "" {
|
||||
if s, err := crypto.EncryptIDCard(idCard, key); err != nil {
|
||||
l.Errorf("查询用户记录表身份证加密失败 queryNo=%s err=%v", queryNo, err)
|
||||
return
|
||||
} else {
|
||||
encIdCard = s
|
||||
}
|
||||
}
|
||||
encMobile := ""
|
||||
if mobile := getStr("mobile"); mobile != "" {
|
||||
if s, err := crypto.EncryptMobile(mobile, secretKey); err != nil {
|
||||
l.Errorf("查询用户记录表手机号加密失败 queryNo=%s err=%v", queryNo, err)
|
||||
return
|
||||
} else {
|
||||
encMobile = s
|
||||
}
|
||||
}
|
||||
agentIdentifier := sql.NullString{}
|
||||
if v, ok := l.ctx.Value("agentIdentifier").(string); ok && v != "" {
|
||||
agentIdentifier = sql.NullString{String: v, Valid: true}
|
||||
}
|
||||
// rec 的 Name、IdCard、Mobile 仅使用密文 encName、encIdCard、encMobile
|
||||
rec := &model.QueryUserRecord{
|
||||
UserId: userID,
|
||||
Name: encName,
|
||||
IdCard: encIdCard,
|
||||
Mobile: encMobile,
|
||||
Product: product,
|
||||
QueryNo: queryNo,
|
||||
OrderId: 0,
|
||||
PlatformOrderId: sql.NullString{},
|
||||
AgentIdentifier: agentIdentifier,
|
||||
}
|
||||
if _, err := l.svcCtx.QueryUserRecordModel.Insert(l.ctx, nil, rec); err != nil {
|
||||
l.Errorf("查询用户记录表写入失败 queryNo=%s err=%v", queryNo, err)
|
||||
}
|
||||
}
|
||||
|
||||
// GetOrCreateUser 获取或创建用户
|
||||
// 1. 如果上下文中已有用户ID,直接返回
|
||||
// 2. 如果是代理查询或APP请求,创建新用户
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
@@ -42,7 +43,8 @@ func (l *BindMobileLogic) BindMobile(req *types.BindMobileReq) (resp *types.Bind
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "绑定手机号, 加密手机号失败: %v", err)
|
||||
}
|
||||
if req.Mobile != "18889793585" {
|
||||
// 开发环境下跳过验证码验证,或者特定手机号跳过(保留原有逻辑)
|
||||
if os.Getenv("ENV") != "development" && req.Mobile != "18889793585" {
|
||||
// 检查手机号是否在一分钟内已发送过验证码
|
||||
redisKey := fmt.Sprintf("%s:%s", "bindMobile", encryptedMobile)
|
||||
cacheCode, err := l.svcCtx.Redis.Get(redisKey)
|
||||
@@ -62,6 +64,10 @@ func (l *BindMobileLogic) BindMobile(req *types.BindMobileReq) (resp *types.Bind
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "绑定手机号, %v", err)
|
||||
}
|
||||
if user != nil {
|
||||
// 被封禁用户禁止绑定/登录
|
||||
if user.Disable == 1 {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.USER_DISABLED), "账号已被封禁")
|
||||
}
|
||||
// 进行平台绑定
|
||||
if claims != nil {
|
||||
if req.Mobile != "18889793585" {
|
||||
|
||||
@@ -33,6 +33,14 @@ func (l *GetTokenLogic) GetToken() (resp *types.MobileCodeLoginResp, err error)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, %v", err)
|
||||
}
|
||||
// 被封禁用户禁止刷新 token
|
||||
user, err := l.svcCtx.UserModel.FindOne(l.ctx, claims.UserId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, %v", err)
|
||||
}
|
||||
if user.Disable == 1 {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.USER_DISABLED), "账号已被封禁")
|
||||
}
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, claims.UserId, claims.UserType)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, %v", err)
|
||||
|
||||
@@ -2,14 +2,15 @@ package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-server/common/xerr"
|
||||
"tydata-server/pkg/lzkit/crypto"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/stores/redis"
|
||||
@@ -37,17 +38,20 @@ func (l *MobileCodeLoginLogic) MobileCodeLogin(req *types.MobileCodeLoginReq) (r
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 加密手机号失败: %+v", err)
|
||||
}
|
||||
// 检查手机号是否在一分钟内已发送过验证码
|
||||
redisKey := fmt.Sprintf("%s:%s", "login", encryptedMobile)
|
||||
cacheCode, err := l.svcCtx.Redis.Get(redisKey)
|
||||
if err != nil {
|
||||
if errors.Is(err, redis.Nil) {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "手机登录, 验证码过期: %s", encryptedMobile)
|
||||
// 开发环境下跳过验证码验证
|
||||
if os.Getenv("ENV") != "development" {
|
||||
// 检查手机号是否在一分钟内已发送过验证码
|
||||
redisKey := fmt.Sprintf("%s:%s", "login", encryptedMobile)
|
||||
cacheCode, err := l.svcCtx.Redis.Get(redisKey)
|
||||
if err != nil {
|
||||
if errors.Is(err, redis.Nil) {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "手机登录, 验证码过期: %s", encryptedMobile)
|
||||
}
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取验证码redis缓存失败, mobile: %s, err: %+v", encryptedMobile, err)
|
||||
}
|
||||
if cacheCode != req.Code {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "手机登录, 验证码不正确: %s", encryptedMobile)
|
||||
}
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取验证码redis缓存失败, mobile: %s, err: %+v", encryptedMobile, err)
|
||||
}
|
||||
if cacheCode != req.Code {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "手机登录, 验证码不正确: %s", encryptedMobile)
|
||||
}
|
||||
var userID int64
|
||||
user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true})
|
||||
@@ -60,6 +64,10 @@ func (l *MobileCodeLoginLogic) MobileCodeLogin(req *types.MobileCodeLoginReq) (r
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 注册用户失败: %+v", err)
|
||||
}
|
||||
} else {
|
||||
// 被封禁用户禁止登录
|
||||
if user.Disable == 1 {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.USER_DISABLED), "账号已被封禁")
|
||||
}
|
||||
userID = user.Id
|
||||
}
|
||||
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID, model.UserTypeNormal)
|
||||
|
||||
@@ -49,7 +49,14 @@ func (l *WxH5AuthLogic) WxH5Auth(req *types.WXH5AuthReq) (resp *types.WXH5AuthRe
|
||||
var userID int64
|
||||
var userType int64
|
||||
if userAuth != nil {
|
||||
// 已存在用户,直接登录
|
||||
// 已存在用户,直接登录(被封禁用户禁止登录)
|
||||
user, err := l.svcCtx.UserModel.FindOne(l.ctx, userAuth.UserId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询用户失败: %v", err)
|
||||
}
|
||||
if user.Disable == 1 {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.USER_DISABLED), "账号已被封禁")
|
||||
}
|
||||
userID = userAuth.UserId
|
||||
userType = model.UserTypeNormal
|
||||
} else {
|
||||
|
||||
@@ -48,7 +48,14 @@ func (l *WxMiniAuthLogic) WxMiniAuth(req *types.WXMiniAuthReq) (resp *types.WXMi
|
||||
var userID int64
|
||||
var userType int64
|
||||
if userAuth != nil {
|
||||
// 已存在用户,直接登录
|
||||
// 已存在用户,直接登录(被封禁用户禁止登录)
|
||||
user, err := l.svcCtx.UserModel.FindOne(l.ctx, userAuth.UserId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询用户失败: %v", err)
|
||||
}
|
||||
if user.Disable == 1 {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.USER_DISABLED), "账号已被封禁")
|
||||
}
|
||||
userID = userAuth.UserId
|
||||
userType = model.UserTypeNormal
|
||||
} else {
|
||||
|
||||
@@ -1,33 +1,60 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-server/common/ctxdata"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/common/xerr"
|
||||
"net/http"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
)
|
||||
|
||||
// 用户封禁状态:0 可用,1 禁用
|
||||
const userDisableStatus = 1
|
||||
|
||||
type UserAuthInterceptorMiddleware struct {
|
||||
UserModel model.UserModel
|
||||
}
|
||||
|
||||
func NewUserAuthInterceptorMiddleware() *UserAuthInterceptorMiddleware {
|
||||
return &UserAuthInterceptorMiddleware{}
|
||||
func NewUserAuthInterceptorMiddleware(userModel model.UserModel) *UserAuthInterceptorMiddleware {
|
||||
return &UserAuthInterceptorMiddleware{UserModel: userModel}
|
||||
}
|
||||
|
||||
func (m *UserAuthInterceptorMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
claims, err := ctxdata.GetClaimsFromCtx(r.Context())
|
||||
if err != nil {
|
||||
httpx.Error(w, errors.Wrapf(xerr.NewErrCode(ErrCodeUnauthorized), "token解析失败: %v", err))
|
||||
m.writeErrorResponse(w, http.StatusUnauthorized, errors.Wrapf(xerr.NewErrCode(ErrCodeUnauthorized), "token解析失败: %v", err))
|
||||
return
|
||||
}
|
||||
if claims.UserType == model.UserTypeTemp {
|
||||
httpx.Error(w, errors.Wrapf(xerr.NewErrCode(xerr.USER_NEED_BIND_MOBILE), "token解析失败: %v", err))
|
||||
m.writeErrorResponse(w, http.StatusUnauthorized, errors.Wrapf(xerr.NewErrCode(xerr.USER_NEED_BIND_MOBILE), "请先绑定手机号"))
|
||||
return
|
||||
}
|
||||
// 封禁校验:用户已被禁用则直接拒绝
|
||||
user, err := m.UserModel.FindOne(r.Context(), claims.UserId)
|
||||
if err != nil {
|
||||
m.writeErrorResponse(w, http.StatusUnauthorized, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户信息失败: %v", err))
|
||||
return
|
||||
}
|
||||
if user.Disable == userDisableStatus {
|
||||
m.writeErrorResponse(w, http.StatusForbidden, xerr.NewErrCode(xerr.USER_DISABLED))
|
||||
return
|
||||
}
|
||||
next(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
// writeErrorResponse 统一返回 code + msg,便于前端展示提示信息
|
||||
func (m *UserAuthInterceptorMiddleware) writeErrorResponse(w http.ResponseWriter, statusCode int, err error) {
|
||||
errcode := xerr.SERVER_COMMON_ERROR
|
||||
errmsg := xerr.MapErrMsg(errcode)
|
||||
if e, ok := errors.Cause(err).(*xerr.CodeError); ok {
|
||||
errcode = e.GetErrCode()
|
||||
errmsg = e.GetErrMsg()
|
||||
}
|
||||
httpx.WriteJson(w, statusCode, result.Error(errcode, errmsg))
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
paylogic "tydata-server/app/main/api/internal/logic/pay"
|
||||
"tydata-server/app/main/api/internal/service"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/app/main/model"
|
||||
@@ -44,12 +46,13 @@ func (l *PaySuccessNotifyUserHandler) ProcessTask(ctx context.Context, t *asynq.
|
||||
if err != nil {
|
||||
return fmt.Errorf("无效的订单ID: %d, %v", payload.OrderID, err)
|
||||
}
|
||||
env := os.Getenv("ENV")
|
||||
if order.Status != "paid" && env != "development" {
|
||||
err = fmt.Errorf("无效的订单: %d", payload.OrderID)
|
||||
// 必须已支付才处理:仅支付宝/微信/苹果回调或 pay_method=test 的异步流程会将订单标为 paid,此处不再按 ENV 放宽
|
||||
if order.Status != "paid" {
|
||||
err = fmt.Errorf("无效的订单状态(非已支付): orderID=%d, status=%s", payload.OrderID, order.Status)
|
||||
logx.Errorf("处理任务失败,原因: %v", err)
|
||||
return asynq.SkipRetry
|
||||
}
|
||||
env := os.Getenv("ENV")
|
||||
product, err := l.svcCtx.ProductModel.FindOne(ctx, order.ProductId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("找不到相关产品: orderID: %d, productID: %d", payload.OrderID, order.ProductId)
|
||||
@@ -140,10 +143,53 @@ func (l *PaySuccessNotifyUserHandler) ProcessTask(ctx context.Context, t *asynq.
|
||||
decryptData = updatedDecryptData
|
||||
}
|
||||
}
|
||||
// 调用API请求服务(开发环境下不调用其它产品,使用默认空报告)
|
||||
var responseData []service.APIResponseData
|
||||
if env == "development" {
|
||||
// 开发环境:生成仅包含基本信息的默认空报告,不调用外部 API
|
||||
// 空报告模式:生成空的报告数据,跳过API调用
|
||||
logx.Infof("空报告模式:订单 %s (ID: %s) 跳过API调用,生成空报告", order.OrderNo, order.Id)
|
||||
// 空数组,表示没有数据;与 json.Marshal 配合得到 []
|
||||
responseData = []service.APIResponseData{}
|
||||
} else {
|
||||
var processErr error
|
||||
responseData, processErr = l.svcCtx.ApiRequestService.ProcessRequests(decryptData, product.Id)
|
||||
if processErr != nil {
|
||||
return l.handleError(ctx, processErr, order, query)
|
||||
}
|
||||
}
|
||||
|
||||
// 调用API请求服务
|
||||
combinedResponse, err := l.svcCtx.ApiRequestService.ProcessRequests(decryptData, product.Id)
|
||||
if err != nil {
|
||||
// 计算成功模块的总成本价
|
||||
totalCostPrice := 0.0
|
||||
if responseData != nil {
|
||||
for _, item := range responseData {
|
||||
if item.Success {
|
||||
// 根据API ID查找功能模块
|
||||
feature, err := l.svcCtx.FeatureModel.FindOneByApiId(ctx, item.ApiID)
|
||||
if err != nil {
|
||||
logx.Errorf("查找功能模块失败, API ID: %s, 错误: %v", item.ApiID, err)
|
||||
continue
|
||||
}
|
||||
// 累加成本价
|
||||
totalCostPrice += feature.CostPrice
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新订单的销售成本
|
||||
order.SalesCost = totalCostPrice
|
||||
updateOrderErr := l.svcCtx.OrderModel.UpdateWithVersion(ctx, nil, order)
|
||||
if updateOrderErr != nil {
|
||||
logx.Errorf("更新订单销售成本失败, 订单ID: %d, 错误: %v", order.Id, updateOrderErr)
|
||||
// 注意:这里不返回错误,因为订单销售成本更新失败不应影响整个查询流程
|
||||
} else {
|
||||
logx.Infof("成功更新订单销售成本, 订单ID: %d, 总成本价: %f", order.Id, totalCostPrice)
|
||||
}
|
||||
|
||||
// 对返回的类型进行二进制转换
|
||||
combinedResponse, marshalErr := json.Marshal(responseData)
|
||||
if marshalErr != nil {
|
||||
err = fmt.Errorf("响应数据转 JSON 失败: %v", marshalErr)
|
||||
return l.handleError(ctx, err, order, query)
|
||||
}
|
||||
// 加密返回响应
|
||||
@@ -212,19 +258,23 @@ func (l *PaySuccessNotifyUserHandler) handleError(ctx context.Context, err error
|
||||
|
||||
// 退款
|
||||
if order.PaymentPlatform == "wechat" {
|
||||
// 微信退款为异步结果,这里只发起退款申请,订单状态与佣金/钱包扣减交由退款回调统一处理
|
||||
refundErr := l.svcCtx.WechatPayService.WeChatRefund(ctx, order.OrderNo, order.Amount, order.Amount)
|
||||
if refundErr != nil {
|
||||
logx.Error(refundErr)
|
||||
return asynq.SkipRetry
|
||||
}
|
||||
logx.Infof("已发起微信退款申请, orderID: %d, amount: %f", order.Id, order.Amount)
|
||||
return asynq.SkipRetry
|
||||
} else {
|
||||
// 支付宝退款为同步结果,这里直接根据返回结果更新订单和佣金/钱包
|
||||
refund, refundErr := l.svcCtx.AlipayService.AliRefund(ctx, order.OrderNo, order.Amount)
|
||||
if refundErr != nil {
|
||||
logx.Error(refundErr)
|
||||
return asynq.SkipRetry
|
||||
}
|
||||
if refund.IsSuccess() {
|
||||
logx.Errorf("支付宝退款成功, orderID: %d", order.Id)
|
||||
logx.Infof("支付宝退款成功, orderID: %d", order.Id)
|
||||
// 更新订单状态为退款
|
||||
order.Status = "refunded"
|
||||
updateOrderErr := l.svcCtx.OrderModel.UpdateWithVersion(ctx, nil, order)
|
||||
@@ -232,6 +282,10 @@ func (l *PaySuccessNotifyUserHandler) handleError(ctx context.Context, err error
|
||||
logx.Errorf("更新订单状态失败,订单ID: %d, 错误: %v", order.Id, updateOrderErr)
|
||||
return fmt.Errorf("更新订单状态失败: %v", updateOrderErr)
|
||||
}
|
||||
|
||||
// 使用公共函数按本次退款金额处理佣金和钱包扣除
|
||||
_ = paylogic.HandleCommissionAndWalletDeduction(ctx, l.svcCtx, nil, order, order.Amount)
|
||||
|
||||
return asynq.SkipRetry
|
||||
} else {
|
||||
logx.Errorf("支付宝退款失败:%v", refundErr)
|
||||
|
||||
@@ -2,9 +2,9 @@ package queue
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"fmt"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
)
|
||||
@@ -24,6 +24,8 @@ func NewCronJob(ctx context.Context, svcCtx *svc.ServiceContext) *CronJob {
|
||||
func (l *CronJob) Register() *asynq.ServeMux {
|
||||
redisClientOpt := asynq.RedisClientOpt{Addr: l.svcCtx.Config.CacheRedis[0].Host, Password: l.svcCtx.Config.CacheRedis[0].Pass}
|
||||
scheduler := asynq.NewScheduler(redisClientOpt, nil)
|
||||
|
||||
// 注册清理查询数据任务
|
||||
task := asynq.NewTask(types.MsgCleanQueryData, nil, nil)
|
||||
_, err := scheduler.Register(TASKTIME, task)
|
||||
if err != nil {
|
||||
@@ -35,6 +37,7 @@ func (l *CronJob) Register() *asynq.ServeMux {
|
||||
mux := asynq.NewServeMux()
|
||||
mux.Handle(types.MsgPaySuccessQuery, NewPaySuccessNotifyUserHandler(l.svcCtx))
|
||||
mux.Handle(types.MsgCleanQueryData, NewCleanQueryDataHandler(l.svcCtx))
|
||||
mux.Handle(types.MsgUnfreezeCommission, NewUnfreezeCommissionHandler(l.svcCtx))
|
||||
|
||||
return mux
|
||||
}
|
||||
|
||||
159
app/main/api/internal/queue/unfreezeCommission.go
Normal file
159
app/main/api/internal/queue/unfreezeCommission.go
Normal file
@@ -0,0 +1,159 @@
|
||||
package queue
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/app/main/model"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
)
|
||||
|
||||
// 定义佣金状态常量
|
||||
const (
|
||||
CommissionStatusReleased = 0 // 已发放
|
||||
CommissionStatusFrozen = 1 // 冻结佣金
|
||||
)
|
||||
|
||||
type UnfreezeCommissionHandler struct {
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewUnfreezeCommissionHandler(svcCtx *svc.ServiceContext) *UnfreezeCommissionHandler {
|
||||
return &UnfreezeCommissionHandler{
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *UnfreezeCommissionHandler) ProcessTask(ctx context.Context, t *asynq.Task) error {
|
||||
now := time.Now()
|
||||
logx.Infof("%s - 开始执行佣金解冻任务", now.Format("2006-01-02 15:04:05"))
|
||||
// 解析任务payload,获取佣金ID
|
||||
var payload types.MsgUnfreezeCommissionPayload
|
||||
if err := json.Unmarshal(t.Payload(), &payload); err != nil {
|
||||
logx.Errorf("解析佣金解冻任务payload失败: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
commissionID := payload.CommissionID
|
||||
if commissionID <= 0 {
|
||||
logx.Errorf("无效的佣金ID: %d", commissionID)
|
||||
return fmt.Errorf("无效的佣金ID: %d", commissionID)
|
||||
}
|
||||
|
||||
// 根据佣金ID查询特定佣金记录
|
||||
commission, err := l.svcCtx.AgentCommissionModel.FindOne(ctx, commissionID)
|
||||
if err != nil {
|
||||
logx.Errorf("查询佣金记录ID %d 失败: %v", commissionID, err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 检查佣金状态是否为冻结状态
|
||||
if commission.Status != CommissionStatusFrozen {
|
||||
logx.Infof("佣金记录ID %d 状态不是冻结状态,当前状态: %d,无需处理", commissionID, commission.Status)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 使用事务处理解冻操作
|
||||
err = l.svcCtx.AgentCommissionModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||
// 获取代理钱包记录
|
||||
agentWallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(ctx, commission.AgentId)
|
||||
if err != nil {
|
||||
logx.Errorf("查询代理ID %d 的钱包记录失败: %v", commission.AgentId, err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 计算当前佣金在发生退款后的“净佣金金额”
|
||||
commissionAmount := commission.Amount - commission.RefundedAmount
|
||||
if commissionAmount <= 0 {
|
||||
logx.Infof("佣金记录ID %d 已被全部退款或无可解冻金额,跳过解冻", commissionID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 更新钱包余额:增加净佣金金额到 balance,减少相应的 frozen_balance
|
||||
agentWallet.Balance += commissionAmount
|
||||
agentWallet.FrozenBalance -= commissionAmount
|
||||
agentWallet.UpdateTime = now
|
||||
|
||||
// 更新钱包数据库(使用 UpdateWithVersion 保持乐观锁)
|
||||
updateWalletErr := l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, agentWallet)
|
||||
if updateWalletErr != nil {
|
||||
// 如果是版本冲突错误,重新查询最新的数据后重试
|
||||
if errors.Is(updateWalletErr, model.ErrNoRowsUpdate) {
|
||||
logx.Infof("代理ID %d 的钱包版本冲突,重新查询最新数据重试", commission.AgentId)
|
||||
latestWallet, findErr := l.svcCtx.AgentWalletModel.FindOneByAgentId(ctx, commission.AgentId)
|
||||
if findErr != nil {
|
||||
logx.Errorf("重新查询代理ID %d 的钱包记录失败: %v", commission.AgentId, findErr)
|
||||
return findErr
|
||||
}
|
||||
// 重新累加金额
|
||||
latestWallet.Balance += commissionAmount
|
||||
latestWallet.FrozenBalance -= commissionAmount
|
||||
latestWallet.UpdateTime = now
|
||||
retryUpdateErr := l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, latestWallet)
|
||||
if retryUpdateErr != nil {
|
||||
logx.Errorf("重试更新代理ID %d 的钱包记录失败: %v", commission.AgentId, retryUpdateErr)
|
||||
return retryUpdateErr
|
||||
}
|
||||
logx.Infof("重试成功,已更新代理ID %d 的钱包记录", commission.AgentId)
|
||||
} else {
|
||||
logx.Errorf("更新代理ID %d 的钱包记录失败: %v", commission.AgentId, updateWalletErr)
|
||||
return updateWalletErr
|
||||
}
|
||||
}
|
||||
|
||||
// 钱包更新成功后,再更新佣金状态为已发放
|
||||
commission.Status = CommissionStatusReleased
|
||||
commission.UpdateTime = now
|
||||
|
||||
// 更新佣金数据库(使用 UpdateWithVersion 保持乐观锁)
|
||||
err = l.svcCtx.AgentCommissionModel.UpdateWithVersion(ctx, session, commission)
|
||||
if err != nil {
|
||||
// 如果是版本冲突错误,重新查询最新的数据后重试
|
||||
if errors.Is(err, model.ErrNoRowsUpdate) {
|
||||
logx.Infof("佣金记录ID %d 版本冲突,重新查询最新数据重试", commissionID)
|
||||
latestCommission, findErr := l.svcCtx.AgentCommissionModel.FindOne(ctx, commissionID)
|
||||
if findErr != nil {
|
||||
logx.Errorf("重新查询佣金记录ID %d 失败: %v", commissionID, findErr)
|
||||
return findErr
|
||||
}
|
||||
// 检查状态是否已被其他操作修改
|
||||
if latestCommission.Status != CommissionStatusFrozen {
|
||||
logx.Errorf("佣金记录ID %d 的状态已被其他操作修改,当前状态: %d", commissionID, latestCommission.Status)
|
||||
return fmt.Errorf("佣金记录状态已被修改")
|
||||
}
|
||||
// 重新更新状态
|
||||
latestCommission.Status = CommissionStatusReleased
|
||||
latestCommission.UpdateTime = now
|
||||
retryUpdateErr := l.svcCtx.AgentCommissionModel.UpdateWithVersion(ctx, session, latestCommission)
|
||||
if retryUpdateErr != nil {
|
||||
logx.Errorf("重试更新佣金记录ID %d 失败: %v", commissionID, retryUpdateErr)
|
||||
return retryUpdateErr
|
||||
}
|
||||
logx.Infof("重试成功,已更新佣金记录ID %d", commissionID)
|
||||
} else {
|
||||
logx.Errorf("更新佣金记录ID %d 失败: %v", commissionID, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
logx.Infof("成功解冻佣金记录ID %d,代理ID %d,佣金金额 %.2f,已将佣金金额从冻结余额转移到可用余额",
|
||||
commissionID, commission.AgentId, commissionAmount)
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
logx.Errorf("%s - 佣金解冻任务失败: %v", now.Format("2006-01-02 15:04:05"), err)
|
||||
return err
|
||||
}
|
||||
|
||||
logx.Infof("%s - 佣金解冻任务完成,佣金ID: %d", now.Format("2006-01-02 15:04:05"), commissionID)
|
||||
return nil
|
||||
}
|
||||
@@ -2,11 +2,15 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"tydata-server/app/main/api/internal/config"
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-server/common/globalkey"
|
||||
"tydata-server/pkg/lzkit/lzUtils"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
)
|
||||
|
||||
@@ -29,6 +33,8 @@ type AgentService struct {
|
||||
AgentPlatformDeductionModel model.AgentPlatformDeductionModel
|
||||
AgentActiveStatModel model.AgentActiveStatModel
|
||||
AgentWithdrawalModel model.AgentWithdrawalModel
|
||||
AgentWalletTransactionModel model.AgentWalletTransactionModel
|
||||
AsynqService *AsynqService
|
||||
}
|
||||
|
||||
func NewAgentService(c config.Config, orderModel model.OrderModel, agentModel model.AgentModel, agentAuditModel model.AgentAuditModel,
|
||||
@@ -38,7 +44,7 @@ func NewAgentService(c config.Config, orderModel model.OrderModel, agentModel mo
|
||||
agentMembershipRechargeOrderModel model.AgentMembershipRechargeOrderModel,
|
||||
agentMembershipUserConfigModel model.AgentMembershipUserConfigModel,
|
||||
agentProductConfigModel model.AgentProductConfigModel, agentPlatformDeductionModel model.AgentPlatformDeductionModel,
|
||||
agentActiveStatModel model.AgentActiveStatModel, agentWithdrawalModel model.AgentWithdrawalModel) *AgentService {
|
||||
agentActiveStatModel model.AgentActiveStatModel, agentWithdrawalModel model.AgentWithdrawalModel, agentWalletTransactionModel model.AgentWalletTransactionModel, asynqService *AsynqService) *AgentService {
|
||||
|
||||
return &AgentService{
|
||||
config: c,
|
||||
@@ -59,6 +65,8 @@ func NewAgentService(c config.Config, orderModel model.OrderModel, agentModel mo
|
||||
AgentPlatformDeductionModel: agentPlatformDeductionModel,
|
||||
AgentActiveStatModel: agentActiveStatModel,
|
||||
AgentWithdrawalModel: agentWithdrawalModel,
|
||||
AgentWalletTransactionModel: agentWalletTransactionModel,
|
||||
AsynqService: asynqService,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,13 +88,13 @@ func (l *AgentService) AgentProcess(ctx context.Context, order *model.Order) err
|
||||
return findAgentProductConfigModelErr
|
||||
}
|
||||
// 平台底价成本
|
||||
PlatformCostAmount, platformCostErr := l.PlatformCost(transCtx, agentID, agentProductConfigModel, session)
|
||||
PlatformCostAmount, platformCostErr := l.PlatformCost(transCtx, agentID, order.Id, agentProductConfigModel, session)
|
||||
if platformCostErr != nil {
|
||||
return platformCostErr
|
||||
}
|
||||
|
||||
// 平台提价成本
|
||||
PlatformPricingAmount, platformPricingErr := l.PlatformPricing(transCtx, agentID, order.Amount, agentProductConfigModel, session)
|
||||
PlatformPricingAmount, platformPricingErr := l.PlatformPricing(transCtx, agentID, order.Id, order.Amount, agentProductConfigModel, session)
|
||||
if platformPricingErr != nil {
|
||||
return platformPricingErr
|
||||
}
|
||||
@@ -113,38 +121,94 @@ func (l *AgentService) AgentProcess(ctx context.Context, order *model.Order) err
|
||||
return findAgentMembersipConfigModelErr
|
||||
}
|
||||
// 定价
|
||||
commissionCost, commissionCostErr := l.CommissionCost(transCtx, agentID, AncestorId, AgentMembershipConfigModel, order.ProductId, session)
|
||||
commissionCost, commissionCostErr := l.CommissionCost(transCtx, agentID, AncestorId, AgentMembershipConfigModel, order.ProductId, order.Id, session)
|
||||
if commissionCostErr != nil {
|
||||
return commissionCostErr
|
||||
}
|
||||
// 提价
|
||||
commissionPricing, commissionPricingErr := l.CommissionPricing(transCtx, agentID, AncestorId, AgentMembershipConfigModel, order.ProductId, order.Amount, session)
|
||||
commissionPricing, commissionPricingErr := l.CommissionPricing(transCtx, agentID, AncestorId, AgentMembershipConfigModel, order.ProductId, order.Amount, order.Id, session)
|
||||
if commissionPricingErr != nil {
|
||||
return commissionPricingErr
|
||||
}
|
||||
|
||||
// 上级克扣的成本
|
||||
descendantDeductedAmount = commissionCost + commissionPricing
|
||||
|
||||
// 佣金
|
||||
// 奖励
|
||||
ancestorCommissionReward, ancestorCommissionErr := l.AncestorCommission(transCtx, agentID, AncestorId, session)
|
||||
if ancestorCommissionErr != nil {
|
||||
return ancestorCommissionErr
|
||||
}
|
||||
|
||||
// 给上级成本以及佣金
|
||||
ancestorCommissionAmount := commissionCost + commissionPricing + ancestorCommissionReward
|
||||
ancestorCommissionAmount := commissionCost + commissionPricing
|
||||
ancestorWallet, findAgentWalletModelErr := l.AgentWalletModel.FindOneByAgentId(transCtx, AncestorId)
|
||||
if findAgentWalletModelErr != nil {
|
||||
return findAgentWalletModelErr
|
||||
}
|
||||
|
||||
ancestorWallet.Balance += ancestorCommissionAmount
|
||||
ancestorWallet.TotalEarnings += ancestorCommissionAmount
|
||||
// 记录变动前的余额
|
||||
balanceBefore := ancestorWallet.Balance
|
||||
frozenBalanceBefore := ancestorWallet.FrozenBalance
|
||||
|
||||
// 奖励不冻结,直接进入balance
|
||||
ancestorWallet.Balance += ancestorCommissionReward
|
||||
|
||||
// 根据安全防御模式配置决定佣金处理方式
|
||||
var commissionStatus int64
|
||||
if l.config.SystemConfig.CommissionSafeMode {
|
||||
// 安全防御模式:佣金冻结在frozen_balance中
|
||||
ancestorWallet.FrozenBalance += ancestorCommissionAmount
|
||||
commissionStatus = 1 // 冻结状态
|
||||
} else {
|
||||
// 非安全防御模式:佣金直接进入balance
|
||||
ancestorWallet.Balance += ancestorCommissionAmount
|
||||
commissionStatus = 0 // 已结算状态
|
||||
}
|
||||
|
||||
// 为上级创建佣金记录
|
||||
ancestorCommissionRecord := model.AgentCommission{
|
||||
AgentId: AncestorId,
|
||||
OrderId: order.Id,
|
||||
Amount: ancestorCommissionAmount,
|
||||
ProductId: order.ProductId,
|
||||
Status: commissionStatus,
|
||||
}
|
||||
insertResult, insertAncestorCommissionErr := l.AgentCommissionModel.Insert(transCtx, session, &ancestorCommissionRecord)
|
||||
if insertAncestorCommissionErr != nil {
|
||||
return insertAncestorCommissionErr
|
||||
}
|
||||
|
||||
ancestorWallet.TotalEarnings += ancestorCommissionAmount + ancestorCommissionReward
|
||||
updateErr := l.AgentWalletModel.UpdateWithVersion(transCtx, session, ancestorWallet)
|
||||
if updateErr != nil {
|
||||
return updateErr
|
||||
}
|
||||
|
||||
// 获取新插入的佣金记录ID
|
||||
commissionID, err := insertResult.LastInsertId()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
commissionIDStr := fmt.Sprintf("%d", commissionID) // 转换为字符串
|
||||
|
||||
// 记录交易流水(佣金收入)
|
||||
transErr := l.CreateWalletTransaction(
|
||||
transCtx,
|
||||
session,
|
||||
AncestorId,
|
||||
model.WalletTransactionTypeCommission,
|
||||
ancestorCommissionAmount, // 变动金额(正数表示增加)
|
||||
balanceBefore, // 变动前余额
|
||||
ancestorWallet.Balance, // 变动后余额
|
||||
frozenBalanceBefore, // 变动前冻结余额
|
||||
ancestorWallet.FrozenBalance, // 变动后冻结余额
|
||||
order.OrderNo, // 关联交易ID(订单号)
|
||||
commissionID, // 关联佣金记录ID
|
||||
fmt.Sprintf("订单佣金收入,佣金记录ID: %s", commissionIDStr), // 备注(包含佣金记录ID)
|
||||
)
|
||||
if transErr != nil {
|
||||
return transErr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,6 +225,39 @@ func (l *AgentService) AgentProcess(ctx context.Context, order *model.Order) err
|
||||
return transErr
|
||||
}
|
||||
|
||||
// 在事务提交后,仅在安全防御模式下触发解冻任务
|
||||
// 注意:这里发送的是任务,实际解冻将在指定时间后由队列处理
|
||||
if l.AsynqService != nil && l.config.SystemConfig.CommissionSafeMode {
|
||||
// 仅在安全防御模式下,才需要发送解冻任务
|
||||
// 获取刚创建的佣金记录ID
|
||||
// 由于我们需要佣金记录ID来触发解冻任务,但事务中无法获取,我们可以在事务后查询
|
||||
builder := l.AgentCommissionModel.SelectBuilder().
|
||||
Where("order_id = ?", order.Id).
|
||||
Where("status = ?", 1). // 只查询状态为冻结的佣金
|
||||
Where("del_state = ?", globalkey.DelStateNo)
|
||||
|
||||
commissions, findErr := l.AgentCommissionModel.FindAll(ctx, builder, "")
|
||||
if findErr != nil {
|
||||
logx.Errorf("查询刚创建的佣金记录失败,订单ID: %d, 错误: %v", order.Id, findErr)
|
||||
return findErr
|
||||
}
|
||||
|
||||
if len(commissions) > 0 {
|
||||
// 为所有新创建的冻结佣金记录触发解冻任务
|
||||
for _, commission := range commissions {
|
||||
// 发送解冻任务,将在10小时后执行
|
||||
sendTaskErr := l.AsynqService.SendUnfreezeCommissionTask(commission.Id)
|
||||
if sendTaskErr != nil {
|
||||
logx.Errorf("发送佣金解冻任务失败,佣金ID: %d, 错误: %v", commission.Id, sendTaskErr)
|
||||
// 不返回错误,因为佣金记录已创建成功,只是解冻任务失败
|
||||
} else {
|
||||
logx.Infof("已发送佣金解冻任务,佣金ID: %d, 代理ID: %d, 金额: %.2f",
|
||||
commission.Id, commission.AgentId, commission.Amount)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -172,24 +269,71 @@ func (l *AgentService) AgentCommission(ctx context.Context, agentID int64, order
|
||||
}
|
||||
// 推广人最终获得代理佣金
|
||||
finalCommission := order.Amount - deductedAmount
|
||||
agentWalletModel.Balance += finalCommission
|
||||
|
||||
// 记录变动前的余额
|
||||
balanceBefore := agentWalletModel.Balance
|
||||
frozenBalanceBefore := agentWalletModel.FrozenBalance
|
||||
|
||||
// 根据安全防御模式配置决定佣金状态和钱包操作
|
||||
if l.config.SystemConfig.CommissionSafeMode {
|
||||
// 安全防御模式:佣金冻结在frozen_balance中
|
||||
agentWalletModel.FrozenBalance += finalCommission
|
||||
} else {
|
||||
// 非安全防御模式:佣金直接进入balance
|
||||
agentWalletModel.Balance += finalCommission
|
||||
}
|
||||
agentWalletModel.TotalEarnings += finalCommission
|
||||
|
||||
// 根据安全防御模式配置决定佣金状态
|
||||
commissionStatus := int64(1) // 默认为冻结状态
|
||||
if !l.config.SystemConfig.CommissionSafeMode {
|
||||
commissionStatus = 0 // 非安全模式直接设置为已结算
|
||||
}
|
||||
|
||||
agentCommission := model.AgentCommission{
|
||||
AgentId: agentID,
|
||||
OrderId: order.Id,
|
||||
Amount: finalCommission,
|
||||
ProductId: order.ProductId,
|
||||
Status: commissionStatus,
|
||||
}
|
||||
_, insertAgentCommissionErr := l.AgentCommissionModel.Insert(ctx, session, &agentCommission)
|
||||
insertResult, insertAgentCommissionErr := l.AgentCommissionModel.Insert(ctx, session, &agentCommission)
|
||||
if insertAgentCommissionErr != nil {
|
||||
return insertAgentCommissionErr
|
||||
}
|
||||
|
||||
// 获取新插入的佣金记录ID(用于日志记录)
|
||||
commissionID, err := insertResult.LastInsertId()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ = commissionID // 暂时忽略该变量,因为我们使用其他方式获取佣金记录
|
||||
|
||||
// 更新钱包
|
||||
updateAgentWalletErr := l.AgentWalletModel.UpdateWithVersion(ctx, session, agentWalletModel)
|
||||
if updateAgentWalletErr != nil {
|
||||
return updateAgentWalletErr
|
||||
}
|
||||
|
||||
// 记录交易流水(佣金收入)
|
||||
transErr := l.CreateWalletTransaction(
|
||||
ctx,
|
||||
session,
|
||||
agentID,
|
||||
model.WalletTransactionTypeCommission,
|
||||
finalCommission, // 变动金额(正数表示增加)
|
||||
balanceBefore, // 变动前余额
|
||||
agentWalletModel.Balance, // 变动后余额
|
||||
frozenBalanceBefore, // 变动前冻结余额
|
||||
agentWalletModel.FrozenBalance, // 变动后冻结余额
|
||||
order.OrderNo, // 关联交易ID(订单号)
|
||||
0, // 关联用户ID
|
||||
"订单佣金收入", // 备注
|
||||
)
|
||||
if transErr != nil {
|
||||
return transErr
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -227,10 +371,11 @@ func (l *AgentService) AncestorCommission(ctx context.Context, descendantId int6
|
||||
}
|
||||
|
||||
// PlatformCost 平台底价成本
|
||||
func (l *AgentService) PlatformCost(ctx context.Context, agentID int64, agentProductConfigModel *model.AgentProductConfig, session sqlx.Session) (float64, error) {
|
||||
func (l *AgentService) PlatformCost(ctx context.Context, agentID int64, orderID int64, agentProductConfigModel *model.AgentProductConfig, session sqlx.Session) (float64, error) {
|
||||
|
||||
costAgentPlatformDeductionModel := model.AgentPlatformDeduction{
|
||||
AgentId: agentID,
|
||||
OrderId: orderID,
|
||||
Amount: agentProductConfigModel.CostPrice,
|
||||
Type: model.AgentDeductionTypeCost,
|
||||
}
|
||||
@@ -243,7 +388,7 @@ func (l *AgentService) PlatformCost(ctx context.Context, agentID int64, agentPro
|
||||
}
|
||||
|
||||
// PlatformPricing 平台提价成本
|
||||
func (l *AgentService) PlatformPricing(ctx context.Context, agentID int64, pricing float64, agentProductConfigModel *model.AgentProductConfig, session sqlx.Session) (float64, error) {
|
||||
func (l *AgentService) PlatformPricing(ctx context.Context, agentID int64, orderID int64, pricing float64, agentProductConfigModel *model.AgentProductConfig, session sqlx.Session) (float64, error) {
|
||||
// 2. 计算平台提价成本
|
||||
if pricing > agentProductConfigModel.PricingStandard {
|
||||
// 超出部分
|
||||
@@ -254,6 +399,7 @@ func (l *AgentService) PlatformPricing(ctx context.Context, agentID int64, prici
|
||||
|
||||
pricingAgentPlatformDeductionModel := model.AgentPlatformDeduction{
|
||||
AgentId: agentID,
|
||||
OrderId: orderID,
|
||||
Amount: overpricingCost,
|
||||
Type: model.AgentDeductionTypePricing,
|
||||
}
|
||||
@@ -268,7 +414,7 @@ func (l *AgentService) PlatformPricing(ctx context.Context, agentID int64, prici
|
||||
}
|
||||
|
||||
// CommissionCost 上级底价成本
|
||||
func (l *AgentService) CommissionCost(ctx context.Context, descendantId int64, AncestorId int64, agentMembershipConfigModel *model.AgentMembershipConfig, productID int64, session sqlx.Session) (float64, error) {
|
||||
func (l *AgentService) CommissionCost(ctx context.Context, descendantId int64, AncestorId int64, agentMembershipConfigModel *model.AgentMembershipConfig, productID int64, orderId int64, session sqlx.Session) (float64, error) {
|
||||
if agentMembershipConfigModel.PriceIncreaseAmount.Valid {
|
||||
// 拥有则查看该上级设定的成本
|
||||
agentMembershipUserConfigModel, findAgentMembershipUserConfigModelErr := l.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(ctx, AncestorId, productID)
|
||||
@@ -288,6 +434,7 @@ func (l *AgentService) CommissionCost(ctx context.Context, descendantId int64, A
|
||||
Amount: deductCostAmount,
|
||||
Type: model.AgentDeductionTypeCost,
|
||||
ProductId: productID,
|
||||
OrderId: sql.NullInt64{Int64: orderId, Valid: true},
|
||||
}
|
||||
|
||||
_, insertAgentCommissionDeductionModelErr := l.AgentCommissionDeductionModel.Insert(ctx, session, &agentCommissionDeductionModel)
|
||||
@@ -301,7 +448,7 @@ func (l *AgentService) CommissionCost(ctx context.Context, descendantId int64, A
|
||||
}
|
||||
|
||||
// CommissionPricing 上级提价成本
|
||||
func (l *AgentService) CommissionPricing(ctx context.Context, descendantId int64, AncestorId int64, agentMembershipConfigModel *model.AgentMembershipConfig, productID int64, pricing float64, session sqlx.Session) (float64, error) {
|
||||
func (l *AgentService) CommissionPricing(ctx context.Context, descendantId int64, AncestorId int64, agentMembershipConfigModel *model.AgentMembershipConfig, productID int64, pricing float64, orderId int64, session sqlx.Session) (float64, error) {
|
||||
//看上级代理等级否有拥有定价标准收益功能
|
||||
if agentMembershipConfigModel.PriceIncreaseMax.Valid && agentMembershipConfigModel.PriceRatio.Valid {
|
||||
// 拥有则查看该上级设定的成本
|
||||
@@ -332,6 +479,7 @@ func (l *AgentService) CommissionPricing(ctx context.Context, descendantId int64
|
||||
Amount: deductCostAmount,
|
||||
Type: model.AgentDeductionTypePricing,
|
||||
ProductId: productID,
|
||||
OrderId: sql.NullInt64{Int64: orderId, Valid: true},
|
||||
}
|
||||
_, insertAgentCommissionDeductionModelErr := l.AgentCommissionDeductionModel.Insert(ctx, session, &agentCommissionDeductionModel)
|
||||
if insertAgentCommissionDeductionModelErr != nil {
|
||||
@@ -384,7 +532,7 @@ func (l *AgentService) GiveUpgradeReward(ctx context.Context, agentID int64, old
|
||||
// 获取各等级的奖励金额
|
||||
var vipRewardAmount float64
|
||||
var svipRewardAmount float64
|
||||
|
||||
|
||||
if agentMembershipConfigModel.LowerConvertVipReward.Valid {
|
||||
vipRewardAmount = agentMembershipConfigModel.LowerConvertVipReward.Float64
|
||||
}
|
||||
@@ -430,7 +578,7 @@ func (l *AgentService) GiveUpgradeReward(ctx context.Context, agentID int64, old
|
||||
Type: rewardType,
|
||||
}
|
||||
|
||||
_, err = l.AgentRewardsModel.Insert(ctx, session, &agentRewards)
|
||||
insertResult, err := l.AgentRewardsModel.Insert(ctx, session, &agentRewards)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -441,12 +589,42 @@ func (l *AgentService) GiveUpgradeReward(ctx context.Context, agentID int64, old
|
||||
return err
|
||||
}
|
||||
|
||||
// 记录变动前的余额
|
||||
balanceBefore := ancestorWallet.Balance
|
||||
frozenBalanceBefore := ancestorWallet.FrozenBalance
|
||||
|
||||
ancestorWallet.Balance += rewardAmount
|
||||
ancestorWallet.TotalEarnings += rewardAmount
|
||||
err = l.AgentWalletModel.UpdateWithVersion(ctx, session, ancestorWallet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 获取新插入的奖励记录ID
|
||||
rewardID, err := insertResult.LastInsertId()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rewardIDStr := fmt.Sprintf("%d", rewardID) // 转换为字符串
|
||||
|
||||
// 记录交易流水(奖励收入)
|
||||
transErr := l.CreateWalletTransaction(
|
||||
ctx,
|
||||
session,
|
||||
ancestorID,
|
||||
model.WalletTransactionTypeReward,
|
||||
rewardAmount, // 变动金额(正数表示增加)
|
||||
balanceBefore, // 变动前余额
|
||||
ancestorWallet.Balance, // 变动后余额
|
||||
frozenBalanceBefore, // 变动前冻结余额
|
||||
ancestorWallet.FrozenBalance, // 变动后冻结余额
|
||||
rewardIDStr, // 关联交易ID(奖励记录ID)
|
||||
agentID, // 关联用户ID(下级代理ID)
|
||||
"下级升级奖励", // 备注
|
||||
)
|
||||
if transErr != nil {
|
||||
return transErr
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -500,7 +678,7 @@ func (l *AgentService) GiveWithdrawReward(ctx context.Context, agentID int64, wi
|
||||
return nil
|
||||
}
|
||||
rewardAmount := withdrawAmount * rewardRatio
|
||||
|
||||
|
||||
if rewardAmount > 0 {
|
||||
// 创建奖励记录
|
||||
agentRewards := model.AgentRewards{
|
||||
@@ -510,7 +688,7 @@ func (l *AgentService) GiveWithdrawReward(ctx context.Context, agentID int64, wi
|
||||
Type: model.AgentRewardsTypeDescendantWithdraw,
|
||||
}
|
||||
|
||||
_, err = l.AgentRewardsModel.Insert(ctx, session, &agentRewards)
|
||||
insertResult, err := l.AgentRewardsModel.Insert(ctx, session, &agentRewards)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -521,12 +699,42 @@ func (l *AgentService) GiveWithdrawReward(ctx context.Context, agentID int64, wi
|
||||
return err
|
||||
}
|
||||
|
||||
// 记录变动前的余额
|
||||
balanceBefore := ancestorWallet.Balance
|
||||
frozenBalanceBefore := ancestorWallet.FrozenBalance
|
||||
|
||||
ancestorWallet.Balance += rewardAmount
|
||||
ancestorWallet.TotalEarnings += rewardAmount
|
||||
err = l.AgentWalletModel.UpdateWithVersion(ctx, session, ancestorWallet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 获取新插入的奖励记录ID
|
||||
rewardID, err := insertResult.LastInsertId()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rewardIDStr := fmt.Sprintf("%d", rewardID) // 转换为字符串
|
||||
|
||||
// 记录交易流水(奖励收入)
|
||||
transErr := l.CreateWalletTransaction(
|
||||
ctx,
|
||||
session,
|
||||
ancestorID,
|
||||
model.WalletTransactionTypeReward,
|
||||
rewardAmount, // 变动金额(正数表示增加)
|
||||
balanceBefore, // 变动前余额
|
||||
ancestorWallet.Balance, // 变动后余额
|
||||
frozenBalanceBefore, // 变动前冻结余额
|
||||
ancestorWallet.FrozenBalance, // 变动后冻结余额
|
||||
rewardIDStr, // 关联交易ID(奖励记录ID)
|
||||
agentID, // 关联用户ID(下级代理ID)
|
||||
"下级提现奖励", // 备注
|
||||
)
|
||||
if transErr != nil {
|
||||
return transErr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -586,3 +794,57 @@ func (l *AgentService) RetryAgentProcess(ctx context.Context, orderID int64) err
|
||||
// 执行代理处理
|
||||
return l.AgentProcess(ctx, order)
|
||||
}
|
||||
|
||||
// CreateWalletTransaction 创建代理钱包流水记录
|
||||
// ctx: 上下文
|
||||
// session: 数据库会话(事务)
|
||||
// agentID: 代理ID
|
||||
// transactionType: 交易类型 (commission/withdraw/freeze/unfreeze/reward/refund/adjust)
|
||||
// amount: 变动金额(正数为增加,负数为减少)
|
||||
// balanceBefore: 变动前余额
|
||||
// balanceAfter: 变动后余额
|
||||
// frozenBalanceBefore: 变动前冻结余额
|
||||
// frozenBalanceAfter: 变动后冻结余额
|
||||
// transactionID: 关联交易ID(订单号、提现申请号等)
|
||||
// relatedUserID: 关联用户ID(如佣金来源用户)
|
||||
// remark: 备注说明
|
||||
func (l *AgentService) CreateWalletTransaction(ctx context.Context, session sqlx.Session,
|
||||
agentID int64, transactionType string, amount float64,
|
||||
balanceBefore, balanceAfter, frozenBalanceBefore, frozenBalanceAfter float64,
|
||||
transactionID string, relatedUserID int64, remark string) error {
|
||||
|
||||
// 处理可空字段
|
||||
var transactionIDField sql.NullString
|
||||
if transactionID != "" {
|
||||
transactionIDField = sql.NullString{String: transactionID, Valid: true}
|
||||
}
|
||||
|
||||
var relatedUserIDField sql.NullInt64
|
||||
if relatedUserID > 0 {
|
||||
relatedUserIDField = sql.NullInt64{Int64: relatedUserID, Valid: true}
|
||||
}
|
||||
|
||||
var remarkField sql.NullString
|
||||
if remark != "" {
|
||||
remarkField = sql.NullString{String: remark, Valid: true}
|
||||
}
|
||||
|
||||
transaction := &model.AgentWalletTransaction{
|
||||
AgentId: agentID,
|
||||
TransactionType: transactionType,
|
||||
Amount: amount,
|
||||
BalanceBefore: balanceBefore,
|
||||
BalanceAfter: balanceAfter,
|
||||
FrozenBalanceBefore: frozenBalanceBefore,
|
||||
FrozenBalanceAfter: frozenBalanceAfter,
|
||||
TransactionId: transactionIDField,
|
||||
RelatedUserId: relatedUserIDField,
|
||||
Remark: remarkField,
|
||||
}
|
||||
|
||||
_, err := l.AgentWalletTransactionModel.Insert(ctx, session, transaction)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "创建代理钱包流水记录失败,agentID: %d, type: %s, amount: %.2f", agentID, transactionType, amount)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ type APIResponseData struct {
|
||||
}
|
||||
|
||||
// ProcessRequests 处理请求
|
||||
func (a *ApiRequestService) ProcessRequests(params []byte, productID int64) ([]byte, error) {
|
||||
func (a *ApiRequestService) ProcessRequests(params []byte, productID int64) ([]APIResponseData, error) {
|
||||
var ctx, cancel = context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
build := a.productFeatureModel.SelectBuilder().Where(squirrel.Eq{
|
||||
@@ -166,12 +166,7 @@ func (a *ApiRequestService) ProcessRequests(params []byte, productID int64) ([]b
|
||||
return nil, fmt.Errorf("请求失败次数超过 %d 次: %v", errorLimit, allErrors)
|
||||
}
|
||||
|
||||
combinedResponse, err := json.Marshal(responseData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("响应数据转 JSON 失败: %v", err)
|
||||
}
|
||||
|
||||
return combinedResponse, nil
|
||||
return responseData, nil
|
||||
}
|
||||
|
||||
// ------------------------------------请求处理器--------------------------
|
||||
@@ -200,6 +195,7 @@ var requestProcessors = map[string]func(*ApiRequestService, []byte) ([]byte, err
|
||||
"IVYZ81NC": (*ApiRequestService).ProcessIVYZ81NCRequest,
|
||||
"IVYZ7F3A": (*ApiRequestService).ProcessIVYZ7F3ARequest,
|
||||
"IVYZ3P9M": (*ApiRequestService).ProcessIVYZ3P9MRequest,
|
||||
"FLXG7E8F": (*ApiRequestService).ProcessFLXG7E8FRequest,
|
||||
}
|
||||
|
||||
// PreprocessRequestApi 调用指定的请求处理函数
|
||||
@@ -1418,6 +1414,7 @@ func (a *ApiRequestService) ProcessIVYZ7F3ARequest(params []byte) ([]byte, error
|
||||
// 直接返回解密后的数据,而不是再次进行JSON编码
|
||||
return convertTianyuanResponse(resp)
|
||||
}
|
||||
|
||||
// ProcessIVYZ3P9MRequest 学历实时查询
|
||||
func (a *ApiRequestService) ProcessIVYZ3P9MRequest(params []byte) ([]byte, error) {
|
||||
idCard := gjson.GetBytes(params, "id_card")
|
||||
@@ -1437,3 +1434,25 @@ func (a *ApiRequestService) ProcessIVYZ3P9MRequest(params []byte) ([]byte, error
|
||||
|
||||
return convertTianyuanResponse(resp)
|
||||
}
|
||||
|
||||
// ProcessFLXG7E8FRequest 个人涉诉
|
||||
func (a *ApiRequestService) ProcessFLXG7E8FRequest(params []byte) ([]byte, error) {
|
||||
idCard := gjson.GetBytes(params, "id_card")
|
||||
name := gjson.GetBytes(params, "name")
|
||||
mobile := gjson.GetBytes(params, "mobile")
|
||||
if !idCard.Exists() || !name.Exists() || !mobile.Exists() {
|
||||
return nil, errors.New("api请求, FLXG7E8F, 获取相关参数失败")
|
||||
}
|
||||
|
||||
resp, err := a.tianyuanapi.CallInterface("FLXG7E8F", map[string]interface{}{
|
||||
"id_card": idCard.String(),
|
||||
"name": name.String(),
|
||||
"mobile_no": mobile.String(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return convertTianyuanResponse(resp)
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"tydata-server/app/main/api/internal/config"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
@@ -58,3 +60,33 @@ func (s *AsynqService) SendQueryTask(orderID int64) error {
|
||||
logx.Infof("发送异步任务成功,任务ID: %s, 队列: %s, 订单号: %d", info.ID, info.Queue, orderID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendUnfreezeCommissionTask 发送佣金解冻任务
|
||||
func (s *AsynqService) SendUnfreezeCommissionTask(commissionID int64) error {
|
||||
// 准备任务的 payload
|
||||
payload := types.MsgUnfreezeCommissionPayload{
|
||||
CommissionID: commissionID,
|
||||
}
|
||||
payloadBytes, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
logx.Errorf("发送佣金解冻任务失败 (无法编码 payload): %v, 佣金ID: %d", err, commissionID)
|
||||
return err
|
||||
}
|
||||
|
||||
options := []asynq.Option{
|
||||
asynq.ProcessIn(time.Duration(s.config.ExtensionTime) * time.Hour), // 10小时后执行
|
||||
asynq.MaxRetry(5), // 设置最大重试次数
|
||||
}
|
||||
task := asynq.NewTask(types.MsgUnfreezeCommission, payloadBytes, options...)
|
||||
|
||||
// 将任务加入队列并获取任务信息
|
||||
info, err := s.client.Enqueue(task)
|
||||
if err != nil {
|
||||
logx.Errorf("发送佣金解冻任务失败 (加入队列失败): %+v, 佣金ID: %d", err, commissionID)
|
||||
return err
|
||||
}
|
||||
|
||||
// 记录成功日志,带上任务 ID 和队列信息
|
||||
logx.Infof("发送佣金解冻任务成功,任务ID: %s, 队列: %s, 佣金ID: %d", info.ID, info.Queue, commissionID)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ func TestGenerateAuthorizationDocument(t *testing.T) {
|
||||
assert.False(t, authDoc.ExpireTime.Valid) // 永久保留,不设置过期时间
|
||||
|
||||
// 验证文件路径格式(兼容Windows和Unix路径分隔符)
|
||||
assert.True(t, strings.Contains(authDoc.FilePath, "data/authorization_docs") ||
|
||||
assert.True(t, strings.Contains(authDoc.FilePath, "data/authorization_docs") ||
|
||||
strings.Contains(authDoc.FilePath, "data\\authorization_docs"))
|
||||
assert.Contains(t, authDoc.FileName, "auth_")
|
||||
assert.Contains(t, authDoc.FileName, ".pdf")
|
||||
@@ -372,7 +372,7 @@ func TestGeneratePDFContent(t *testing.T) {
|
||||
t.Logf("📁 文件路径: %s", filePath)
|
||||
t.Logf("🔗 相对路径: %s", relativePath)
|
||||
t.Logf("📊 文件大小: %d 字节", len(pdfBytes))
|
||||
|
||||
|
||||
// 获取绝对路径
|
||||
absPath, _ := filepath.Abs(filePath)
|
||||
t.Logf("📍 绝对路径: %s", absPath)
|
||||
@@ -430,16 +430,16 @@ func TestSavePDFToLocal(t *testing.T) {
|
||||
t.Logf("📁 文件路径: %s", filePath)
|
||||
t.Logf("🔗 相对路径: %s", relativePath)
|
||||
t.Logf("📊 文件大小: %d 字节", len(pdfBytes))
|
||||
|
||||
|
||||
// 获取绝对路径
|
||||
absPath, _ := filepath.Abs(filePath)
|
||||
t.Logf("📍 绝对路径: %s", absPath)
|
||||
|
||||
|
||||
// 验证文件内容
|
||||
fileInfo, err := os.Stat(filePath)
|
||||
assert.NoError(t, err)
|
||||
assert.Greater(t, fileInfo.Size(), int64(1000)) // 文件应该大于1KB
|
||||
|
||||
|
||||
t.Logf("🎉 文件保存验证通过!")
|
||||
} else {
|
||||
t.Errorf("❌ PDF文件保存失败: %v", err)
|
||||
@@ -648,18 +648,18 @@ func TestGeneratePDFFile(t *testing.T) {
|
||||
t.Logf("📁 文件路径: %s", authDoc.FilePath)
|
||||
t.Logf("🔗 相对路径: %s", authDoc.FileUrl)
|
||||
t.Logf("📊 文件大小: %d 字节", authDoc.FileSize)
|
||||
|
||||
|
||||
// 验证文件内容
|
||||
fileInfo, err := os.Stat(authDoc.FilePath)
|
||||
assert.NoError(t, err)
|
||||
assert.Greater(t, fileInfo.Size(), int64(1000)) // 文件应该大于1KB
|
||||
|
||||
|
||||
// 验证文件名格式
|
||||
assert.Regexp(t, `^auth_999_888_\d{8}_\d{6}\.pdf$`, authDoc.FileName)
|
||||
|
||||
|
||||
// 验证路径格式
|
||||
assert.Regexp(t, `^\d{4}/\d{2}/auth_999_888_\d{8}_\d{6}\.pdf$`, authDoc.FileUrl)
|
||||
|
||||
|
||||
t.Logf("🎉 所有验证通过!")
|
||||
} else {
|
||||
t.Errorf("❌ PDF文件未创建: %s", authDoc.FilePath)
|
||||
|
||||
@@ -206,8 +206,35 @@ func (w *WechatPayService) CreateWechatMiniProgramOrder(ctx context.Context, amo
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("微信支付订单创建失败: %v, 状态码: %d", err, result.Response.StatusCode)
|
||||
}
|
||||
// 返回预支付交易会话标识
|
||||
return resp, nil
|
||||
// 显式转为 map,确保小程序 uni.requestPayment 能正确解析(避免指针序列化问题)
|
||||
return jsapiRespToMap(resp), nil
|
||||
}
|
||||
|
||||
// jsapiRespToMap 将 PrepayWithRequestPaymentResponse 转为 map,供小程序/JSAPI 调起支付
|
||||
func jsapiRespToMap(resp *jsapi.PrepayWithRequestPaymentResponse) map[string]string {
|
||||
m := make(map[string]string)
|
||||
if resp == nil {
|
||||
return m
|
||||
}
|
||||
if resp.Appid != nil {
|
||||
m["appId"] = *resp.Appid
|
||||
}
|
||||
if resp.TimeStamp != nil {
|
||||
m["timeStamp"] = *resp.TimeStamp
|
||||
}
|
||||
if resp.NonceStr != nil {
|
||||
m["nonceStr"] = *resp.NonceStr
|
||||
}
|
||||
if resp.Package != nil {
|
||||
m["package"] = *resp.Package
|
||||
}
|
||||
if resp.SignType != nil {
|
||||
m["signType"] = *resp.SignType
|
||||
}
|
||||
if resp.PaySign != nil {
|
||||
m["paySign"] = *resp.PaySign
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// CreateWechatH5Order 创建微信H5支付订单
|
||||
@@ -237,8 +264,7 @@ func (w *WechatPayService) CreateWechatH5Order(ctx context.Context, amount float
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("微信支付订单创建失败: %v, 状态码: %d", err, result.Response.StatusCode)
|
||||
}
|
||||
// 返回预支付交易会话标识
|
||||
return resp, nil
|
||||
return jsapiRespToMap(resp), nil
|
||||
}
|
||||
|
||||
// CreateWechatOrder 创建微信支付订单(集成 APP、H5、小程序)
|
||||
|
||||
@@ -39,6 +39,7 @@ type ServiceContext struct {
|
||||
OrderModel model.OrderModel
|
||||
OrderRefundModel model.OrderRefundModel
|
||||
QueryModel model.QueryModel
|
||||
QueryUserRecordModel model.QueryUserRecordModel
|
||||
QueryCleanupLogModel model.QueryCleanupLogModel
|
||||
QueryCleanupDetailModel model.QueryCleanupDetailModel
|
||||
QueryCleanupConfigModel model.QueryCleanupConfigModel
|
||||
@@ -63,6 +64,7 @@ type ServiceContext struct {
|
||||
AgentRealNameModel model.AgentRealNameModel
|
||||
AgentWithdrawalTaxModel model.AgentWithdrawalTaxModel
|
||||
AgentWithdrawalTaxExemptionModel model.AgentWithdrawalTaxExemptionModel
|
||||
AgentWalletTransactionModel model.AgentWalletTransactionModel
|
||||
|
||||
// 管理后台相关模型
|
||||
AdminApiModel model.AdminApiModel
|
||||
@@ -127,6 +129,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
// ============================== 订单相关模型 ==============================
|
||||
orderModel := model.NewOrderModel(db, cacheConf)
|
||||
queryModel := model.NewQueryModel(db, cacheConf)
|
||||
queryUserRecordModel := model.NewQueryUserRecordModel(db, cacheConf)
|
||||
orderRefundModel := model.NewOrderRefundModel(db, cacheConf)
|
||||
queryCleanupLogModel := model.NewQueryCleanupLogModel(db, cacheConf)
|
||||
queryCleanupDetailModel := model.NewQueryCleanupDetailModel(db, cacheConf)
|
||||
@@ -152,6 +155,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
agentRealNameModel := model.NewAgentRealNameModel(db, cacheConf)
|
||||
agentWithdrawalTaxModel := model.NewAgentWithdrawalTaxModel(db, cacheConf)
|
||||
agentWithdrawalTaxExemptionModel := model.NewAgentWithdrawalTaxExemptionModel(db, cacheConf)
|
||||
agentWalletTransactionModel := model.NewAgentWalletTransactionModel(db, cacheConf)
|
||||
// ============================== 管理后台相关模型 ==============================
|
||||
adminApiModel := model.NewAdminApiModel(db, cacheConf)
|
||||
adminMenuModel := model.NewAdminMenuModel(db, cacheConf)
|
||||
@@ -194,7 +198,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
agentCommissionModel, agentCommissionDeductionModel, agentWalletModel, agentLinkModel,
|
||||
agentOrderModel, agentRewardsModel, agentMembershipConfigModel, agentMembershipRechargeOrderModel,
|
||||
agentMembershipUserConfigModel, agentProductConfigModel, agentPlatformDeductionModel,
|
||||
agentActiveStatModel, agentWithdrawalModel)
|
||||
agentActiveStatModel, agentWithdrawalModel, agentWalletTransactionModel, asynqService)
|
||||
userService := service.NewUserService(&c, userModel, userAuthModel, userTempModel, agentModel)
|
||||
dictService := service.NewDictService(adminDictTypeModel, adminDictDataModel)
|
||||
adminPromotionLinkStatsService := service.NewAdminPromotionLinkStatsService(adminPromotionLinkModel,
|
||||
@@ -219,7 +223,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
Config: c,
|
||||
Redis: redisClient,
|
||||
AuthInterceptor: middleware.NewAuthInterceptorMiddleware(c).Handle,
|
||||
UserAuthInterceptor: middleware.NewUserAuthInterceptorMiddleware().Handle,
|
||||
UserAuthInterceptor: middleware.NewUserAuthInterceptorMiddleware(userModel).Handle,
|
||||
AdminAuthInterceptor: middleware.NewAdminAuthInterceptorMiddleware(c,
|
||||
adminUserModel, adminUserRoleModel, adminRoleModel, adminApiModel, adminRoleApiModel).Handle,
|
||||
|
||||
@@ -236,6 +240,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
// 订单相关模型
|
||||
OrderModel: orderModel,
|
||||
QueryModel: queryModel,
|
||||
QueryUserRecordModel: queryUserRecordModel,
|
||||
OrderRefundModel: orderRefundModel,
|
||||
QueryCleanupLogModel: queryCleanupLogModel,
|
||||
QueryCleanupDetailModel: queryCleanupDetailModel,
|
||||
@@ -261,6 +266,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
AgentRealNameModel: agentRealNameModel,
|
||||
AgentWithdrawalTaxModel: agentWithdrawalTaxModel,
|
||||
AgentWithdrawalTaxExemptionModel: agentWithdrawalTaxExemptionModel,
|
||||
AgentWalletTransactionModel: agentWalletTransactionModel,
|
||||
|
||||
// 管理后台相关模型
|
||||
AdminApiModel: adminApiModel,
|
||||
|
||||
@@ -3,3 +3,7 @@ package types
|
||||
type MsgPaySuccessQueryPayload struct {
|
||||
OrderID int64 `json:"order_id"`
|
||||
}
|
||||
|
||||
type MsgUnfreezeCommissionPayload struct {
|
||||
CommissionID int64 `json:"commission_id"`
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ type CompanyInfoReq struct {
|
||||
Name string `json:"name" validate:"required,name"`
|
||||
IDCard string `json:"id_card" validate:"required,idCard"`
|
||||
Mobile string `json:"mobile" validate:"required,mobile"`
|
||||
Code string `json:"code" validate:"required"`
|
||||
// Code string `json:"code" validate:"required"` // 暂不校验验证码
|
||||
}
|
||||
|
||||
// RentalInfo 查询请求结构
|
||||
|
||||
@@ -2,3 +2,4 @@ package types
|
||||
|
||||
const MsgPaySuccessQuery = "msg:pay_success:query"
|
||||
const MsgCleanQueryData = "msg:clean_query_data"
|
||||
const MsgUnfreezeCommission = "msg:unfreeze_commission"
|
||||
|
||||
@@ -36,6 +36,16 @@ type AdminAssignRoleApiResp struct {
|
||||
Success bool `json:"success"`
|
||||
}
|
||||
|
||||
type AdminBatchUnfreezeAgentCommissionReq struct {
|
||||
AgentId *int64 `json:"agent_id,optional"` // 代理ID,可选。如果不传则解冻所有冻结中的佣金
|
||||
}
|
||||
|
||||
type AdminBatchUnfreezeAgentCommissionResp struct {
|
||||
Success bool `json:"success"` // 是否成功
|
||||
Count int64 `json:"count"` // 解冻的数量
|
||||
Amount float64 `json:"amount"` // 解冻的总金额
|
||||
}
|
||||
|
||||
type AdminBatchUpdateApiStatusReq struct {
|
||||
Ids []int64 `json:"ids"`
|
||||
Status int64 `json:"status"`
|
||||
@@ -214,11 +224,14 @@ type AdminGetAgentCommissionDeductionListResp struct {
|
||||
}
|
||||
|
||||
type AdminGetAgentCommissionListReq struct {
|
||||
Page int64 `form:"page"` // 页码
|
||||
PageSize int64 `form:"pageSize"` // 每页数量
|
||||
AgentId *int64 `form:"agent_id,optional"` // 代理ID(可选)
|
||||
ProductName *string `form:"product_name,optional"` // 产品名(可选)
|
||||
Status *int64 `form:"status,optional"` // 状态(可选)
|
||||
Page int64 `form:"page"` // 页码
|
||||
PageSize int64 `form:"pageSize"` // 每页数量
|
||||
AgentId *int64 `form:"agent_id,optional"` // 代理ID(可选)
|
||||
OrderId *int64 `form:"order_id,optional"` // 订单ID(可选)
|
||||
ProductName *string `form:"product_name,optional"` // 产品名(可选)
|
||||
Status *int64 `form:"status,optional"` // 状态(可选)
|
||||
CreateTimeStart *string `form:"create_time_start,optional"` // 创建时间开始(可选)
|
||||
CreateTimeEnd *string `form:"create_time_end,optional"` // 创建时间结束(可选)
|
||||
}
|
||||
|
||||
type AdminGetAgentCommissionListResp struct {
|
||||
@@ -239,6 +252,13 @@ type AdminGetAgentLinkListResp struct {
|
||||
Items []AgentLinkListItem `json:"items"` // 列表数据
|
||||
}
|
||||
|
||||
type AdminGetAgentLinkProductStatisticsReq struct {
|
||||
}
|
||||
|
||||
type AdminGetAgentLinkProductStatisticsResp struct {
|
||||
Items []AgentLinkProductStatisticsItem `json:"items"` // 列表数据
|
||||
}
|
||||
|
||||
type AdminGetAgentListReq struct {
|
||||
Page int64 `form:"page"` // 页码
|
||||
PageSize int64 `form:"pageSize"` // 每页数量
|
||||
@@ -279,6 +299,14 @@ type AdminGetAgentMembershipRechargeOrderListResp struct {
|
||||
Items []AgentMembershipRechargeOrderListItem `json:"items"` // 列表数据
|
||||
}
|
||||
|
||||
type AdminGetAgentOrderStatisticsReq struct {
|
||||
}
|
||||
|
||||
type AdminGetAgentOrderStatisticsResp struct {
|
||||
TotalAgentOrderCount int64 `json:"total_agent_order_count"` // 总代理订单数
|
||||
TodayAgentOrderCount int64 `json:"today_agent_order_count"` // 今日代理订单数
|
||||
}
|
||||
|
||||
type AdminGetAgentPlatformDeductionListReq struct {
|
||||
Page int64 `form:"page"` // 页码
|
||||
PageSize int64 `form:"pageSize"` // 每页数量
|
||||
@@ -317,12 +345,45 @@ type AdminGetAgentRewardListResp struct {
|
||||
Items []AgentRewardListItem `json:"items"` // 列表数据
|
||||
}
|
||||
|
||||
type AdminGetAgentStatisticsReq struct {
|
||||
}
|
||||
|
||||
type AdminGetAgentStatisticsResp struct {
|
||||
TotalAgentCount int64 `json:"total_agent_count"` // 总代理数
|
||||
TodayAgentCount int64 `json:"today_agent_count"` // 今日新增代理数
|
||||
}
|
||||
|
||||
type AdminGetAgentWalletReq struct {
|
||||
AgentId int64 `path:"agent_id"` // 代理ID
|
||||
}
|
||||
|
||||
type AdminGetAgentWalletResp struct {
|
||||
Balance float64 `json:"balance"` // 可用余额
|
||||
FrozenBalance float64 `json:"frozen_balance"` // 冻结余额
|
||||
TotalEarnings float64 `json:"total_earnings"` // 总收益
|
||||
}
|
||||
|
||||
type AdminGetAgentWalletTransactionListReq struct {
|
||||
Page int64 `form:"page"` // 页码
|
||||
PageSize int64 `form:"pageSize"` // 每页数量
|
||||
AgentId int64 `form:"agent_id"` // 代理ID
|
||||
TransactionType *string `form:"transaction_type,optional"` // 交易类型(可选)
|
||||
CreateTimeStart *string `form:"create_time_start,optional"` // 创建时间开始(可选)
|
||||
CreateTimeEnd *string `form:"create_time_end,optional"` // 创建时间结束(可选)
|
||||
}
|
||||
|
||||
type AdminGetAgentWalletTransactionListResp struct {
|
||||
Total int64 `json:"total"` // 总数
|
||||
Items []AgentWalletTransactionListItem `json:"items"` // 列表数据
|
||||
}
|
||||
|
||||
type AdminGetAgentWithdrawalListReq struct {
|
||||
Page int64 `form:"page"` // 页码
|
||||
PageSize int64 `form:"pageSize"` // 每页数量
|
||||
AgentId *int64 `form:"agent_id,optional"` // 代理ID(可选)
|
||||
Status *int64 `form:"status,optional"` // 状态(可选)
|
||||
WithdrawNo *string `form:"withdraw_no,optional"` // 提现单号(可选)
|
||||
Page int64 `form:"page"` // 页码
|
||||
PageSize int64 `form:"pageSize"` // 每页数量
|
||||
AgentId *int64 `form:"agent_id,optional"` // 代理ID(可选)
|
||||
Status *int64 `form:"status,optional"` // 状态(可选)
|
||||
WithdrawNo *string `form:"withdraw_no,optional"` // 提现单号(可选)
|
||||
WithdrawType *int64 `form:"withdraw_type,optional"` // 提现类型(可选)1-支付宝,2-银行卡
|
||||
}
|
||||
|
||||
type AdminGetAgentWithdrawalListResp struct {
|
||||
@@ -386,11 +447,10 @@ type AdminGetFeatureExampleResp struct {
|
||||
}
|
||||
|
||||
type AdminGetFeatureListReq struct {
|
||||
Page int64 `form:"page"` // 页码
|
||||
PageSize int64 `form:"pageSize"` // 每页数量
|
||||
ApiId *string `form:"api_id,optional"` // API标识
|
||||
Name *string `form:"name,optional"` // 描述
|
||||
CostPrice *float64 `form:"cost_price,optional"` // 成本价
|
||||
Page int64 `form:"page"` // 页码
|
||||
PageSize int64 `form:"pageSize"` // 每页数量
|
||||
ApiId *string `form:"api_id,optional"` // API标识
|
||||
Name *string `form:"name,optional"` // 描述
|
||||
}
|
||||
|
||||
type AdminGetFeatureListResp struct {
|
||||
@@ -443,6 +503,7 @@ type AdminGetOrderDetailResp struct {
|
||||
PaymentPlatform string `json:"payment_platform"` // 支付方式
|
||||
PaymentScene string `json:"payment_scene"` // 支付平台
|
||||
Amount float64 `json:"amount"` // 金额
|
||||
SalesCost float64 `json:"sales_cost"` // 成本价
|
||||
Status string `json:"status"` // 支付状态:pending-待支付,paid-已支付,refunded-已退款,closed-已关闭,failed-支付失败
|
||||
QueryState string `json:"query_state"` // 查询状态:pending-待查询,success-查询成功,failed-查询失败 processing-查询中
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
@@ -471,6 +532,10 @@ type AdminGetOrderListReq struct {
|
||||
PayTimeEnd string `form:"pay_time_end,optional"` // 支付时间结束
|
||||
RefundTimeStart string `form:"refund_time_start,optional"` // 退款时间开始
|
||||
RefundTimeEnd string `form:"refund_time_end,optional"` // 退款时间结束
|
||||
SalesCost float64 `form:"sales_cost,optional"` // 成本价
|
||||
QueryName string `form:"query_name,optional"` // 被查询人姓名(通过 query_user_record 表追溯订单)
|
||||
QueryIdCard string `form:"query_id_card,optional"` // 被查询人身份证(通过 query_user_record 表追溯订单)
|
||||
QueryMobile string `form:"query_mobile,optional"` // 被查询人手机号(通过 query_user_record 表追溯订单)
|
||||
}
|
||||
|
||||
type AdminGetOrderListResp struct {
|
||||
@@ -478,6 +543,21 @@ type AdminGetOrderListResp struct {
|
||||
Items []OrderListItem `json:"items"` // 列表
|
||||
}
|
||||
|
||||
type AdminGetOrderSourceStatisticsReq struct {
|
||||
}
|
||||
|
||||
type AdminGetOrderSourceStatisticsResp struct {
|
||||
Items []OrderSourceStatisticsItem `json:"items"` // 订单来源统计列表
|
||||
}
|
||||
|
||||
type AdminGetOrderStatisticsReq struct {
|
||||
Dimension string `form:"dimension"` // 时间维度:day-日(当月1号到今天),month-月(今年1月到当月),year-年(过去5年),all-全部(按日统计)
|
||||
}
|
||||
|
||||
type AdminGetOrderStatisticsResp struct {
|
||||
Items []OrderStatisticsItem `json:"items"` // 订单统计列表
|
||||
}
|
||||
|
||||
type AdminGetPlatformUserDetailReq struct {
|
||||
Id int64 `path:"id"` // 用户ID
|
||||
}
|
||||
@@ -488,6 +568,7 @@ type AdminGetPlatformUserDetailResp struct {
|
||||
Nickname string `json:"nickname"` // 昵称
|
||||
Info string `json:"info"` // 备注信息
|
||||
Inside int64 `json:"inside"` // 是否内部用户 1-是 0-否
|
||||
Disable int64 `json:"disable"` // 封禁状态 0-可用 1-禁用
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
UpdateTime string `json:"update_time"` // 更新时间
|
||||
}
|
||||
@@ -602,6 +683,24 @@ type AdminGetQueryDetailByOrderIdResp struct {
|
||||
QueryState string `json:"query_state"` // 查询状态
|
||||
}
|
||||
|
||||
type AdminGetRefundStatisticsReq struct {
|
||||
}
|
||||
|
||||
type AdminGetRefundStatisticsResp struct {
|
||||
TotalRefundAmount float64 `json:"total_refund_amount"` // 总退款金额
|
||||
TodayRefundAmount float64 `json:"today_refund_amount"` // 今日退款金额
|
||||
}
|
||||
|
||||
type AdminGetRevenueStatisticsReq struct {
|
||||
}
|
||||
|
||||
type AdminGetRevenueStatisticsResp struct {
|
||||
TotalRevenueAmount float64 `json:"total_revenue_amount"` // 总收入金额
|
||||
TodayRevenueAmount float64 `json:"today_revenue_amount"` // 今日收入金额
|
||||
TotalProfitAmount float64 `json:"total_profit_amount"` // 总利润金额
|
||||
TodayProfitAmount float64 `json:"today_profit_amount"` // 今日利润金额
|
||||
}
|
||||
|
||||
type AdminGetRoleApiListReq struct {
|
||||
RoleId int64 `path:"role_id"`
|
||||
}
|
||||
@@ -610,6 +709,10 @@ type AdminGetRoleApiListResp struct {
|
||||
Items []AdminRoleApiInfo `json:"items"`
|
||||
}
|
||||
|
||||
type AdminGetSystemConfigResp struct {
|
||||
CommissionSafeMode bool `json:"commission_safe_mode"` // 佣金安全防御模式
|
||||
}
|
||||
|
||||
type AdminGetUserDetailReq struct {
|
||||
Id int64 `path:"id"` // 用户ID
|
||||
}
|
||||
@@ -637,6 +740,16 @@ type AdminGetUserListResp struct {
|
||||
Items []AdminUserListItem `json:"items"` // 列表
|
||||
}
|
||||
|
||||
type AdminGetWithdrawalStatisticsReq struct {
|
||||
}
|
||||
|
||||
type AdminGetWithdrawalStatisticsResp struct {
|
||||
TotalWithdrawalAmount float64 `json:"total_withdrawal_amount"` // 总提现金额
|
||||
TodayWithdrawalAmount float64 `json:"today_withdrawal_amount"` // 今日提现金额
|
||||
TotalActualAmount float64 `json:"total_actual_amount"` // 总实际到账金额
|
||||
TotalTaxAmount float64 `json:"total_tax_amount"` // 总扣税金额
|
||||
}
|
||||
|
||||
type AdminLoginReq struct {
|
||||
Username string `json:"username" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
@@ -717,6 +830,15 @@ type AdminRoleApiInfo struct {
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type AdminUpdateAgentCommissionStatusReq struct {
|
||||
Id int64 `json:"id"` // 佣金记录ID
|
||||
Status int64 `json:"status"` // 状态:0-已结算,1-冻结中,2-已取消
|
||||
}
|
||||
|
||||
type AdminUpdateAgentCommissionStatusResp struct {
|
||||
Success bool `json:"success"` // 是否成功
|
||||
}
|
||||
|
||||
type AdminUpdateAgentMembershipConfigReq struct {
|
||||
Id int64 `json:"id"` // 主键
|
||||
LevelName string `json:"level_name"` // 会员级别名称
|
||||
@@ -752,6 +874,16 @@ type AdminUpdateAgentProductionConfigResp struct {
|
||||
Success bool `json:"success"` // 是否成功
|
||||
}
|
||||
|
||||
type AdminUpdateAgentWalletBalanceReq struct {
|
||||
AgentId int64 `json:"agent_id"` // 代理ID
|
||||
Amount float64 `json:"amount"` // 修改金额(正数增加,负数减少)
|
||||
}
|
||||
|
||||
type AdminUpdateAgentWalletBalanceResp struct {
|
||||
Success bool `json:"success"` // 是否成功
|
||||
Balance float64 `json:"balance"` // 修改后的余额
|
||||
}
|
||||
|
||||
type AdminUpdateApiReq struct {
|
||||
Id int64 `path:"id"`
|
||||
ApiName string `json:"api_name"`
|
||||
@@ -818,6 +950,7 @@ type AdminUpdatePlatformUserReq struct {
|
||||
Nickname *string `json:"nickname,optional"` // 昵称
|
||||
Info *string `json:"info,optional"` // 备注信息
|
||||
Inside *int64 `json:"inside,optional"` // 是否内部用户 1-是 0-否
|
||||
Disable *int64 `json:"disable,optional"` // 封禁状态 0-可用 1-禁用
|
||||
}
|
||||
|
||||
type AdminUpdatePlatformUserResp struct {
|
||||
@@ -866,6 +999,14 @@ type AdminUpdateRoleApiResp struct {
|
||||
Success bool `json:"success"`
|
||||
}
|
||||
|
||||
type AdminUpdateSystemConfigReq struct {
|
||||
CommissionSafeMode *bool `json:"commission_safe_mode,optional"` // 佣金安全防御模式:true-冻结模式,false-直接结算模式
|
||||
}
|
||||
|
||||
type AdminUpdateSystemConfigResp struct {
|
||||
Success bool `json:"success"` // 是否成功
|
||||
}
|
||||
|
||||
type AdminUpdateUserReq struct {
|
||||
Id int64 `path:"id"` // 用户ID
|
||||
Username *string `json:"username,optional"` // 用户名
|
||||
@@ -971,6 +1112,11 @@ type AgentLinkListItem struct {
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
}
|
||||
|
||||
type AgentLinkProductStatisticsItem struct {
|
||||
ProductName string `json:"product_name"` // 产品名称
|
||||
LinkCount int64 `json:"link_count"` // 推广链接数量
|
||||
}
|
||||
|
||||
type AgentListItem struct {
|
||||
Id int64 `json:"id"` // 主键
|
||||
UserId int64 `json:"user_id"` // 用户ID
|
||||
@@ -1134,6 +1280,21 @@ type AgentSubordinateList struct {
|
||||
TotalContribution float64 `json:"total_contribution"` // 总贡献
|
||||
}
|
||||
|
||||
type AgentWalletTransactionListItem struct {
|
||||
Id int64 `json:"id"` // 主键
|
||||
AgentId int64 `json:"agent_id"` // 代理ID
|
||||
TransactionType string `json:"transaction_type"` // 交易类型
|
||||
Amount float64 `json:"amount"` // 变动金额
|
||||
BalanceBefore float64 `json:"balance_before"` // 变动前余额
|
||||
BalanceAfter float64 `json:"balance_after"` // 变动后余额
|
||||
FrozenBalanceBefore float64 `json:"frozen_balance_before"` // 变动前冻结余额
|
||||
FrozenBalanceAfter float64 `json:"frozen_balance_after"` // 变动后冻结余额
|
||||
TransactionId *string `json:"transaction_id"` // 关联交易ID
|
||||
RelatedUserId *int64 `json:"related_user_id"` // 关联用户ID
|
||||
Remark *string `json:"remark"` // 备注说明
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
}
|
||||
|
||||
type AgentWithdrawalListItem struct {
|
||||
Id int64 `json:"id"` // 主键
|
||||
AgentId int64 `json:"agent_id"` // 代理ID
|
||||
@@ -1182,11 +1343,14 @@ type BindMobileResp struct {
|
||||
}
|
||||
|
||||
type Commission struct {
|
||||
OrderId string `json:"order_id"` // 订单号
|
||||
ProductName string `json:"product_name"`
|
||||
Amount float64 `json:"amount"`
|
||||
CreateTime string `json:"create_time"`
|
||||
QueryParams map[string]interface{} `json:"query_params,omitempty"`
|
||||
OrderId string `json:"order_id"` // 订单号
|
||||
ProductName string `json:"product_name"`
|
||||
Amount float64 `json:"amount"` // 原始佣金金额
|
||||
RefundedAmount float64 `json:"refunded_amount"` // 已退款佣金金额
|
||||
NetAmount float64 `json:"net_amount"` // 剩余净佣金金额 = amount - refunded_amount
|
||||
Status int64 `json:"status"` // 状态:0-已结算,1-冻结中,2-已退款
|
||||
CreateTime string `json:"create_time"`
|
||||
QueryParams map[string]interface{} `json:"query_params,omitempty"`
|
||||
}
|
||||
|
||||
type CreateMenuReq struct {
|
||||
@@ -1643,6 +1807,7 @@ type OrderListItem struct {
|
||||
PaymentPlatform string `json:"payment_platform"` // 支付方式
|
||||
PaymentScene string `json:"payment_scene"` // 支付平台
|
||||
Amount float64 `json:"amount"` // 金额
|
||||
SalesCost float64 `json:"sales_cost"` // 成本价
|
||||
Status string `json:"status"` // 支付状态:pending-待支付,paid-已支付,refunded-已退款,closed-已关闭,failed-支付失败
|
||||
QueryState string `json:"query_state"` // 查询状态:pending-待查询,success-查询成功,failed-查询失败 processing-查询中
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
@@ -1653,6 +1818,17 @@ type OrderListItem struct {
|
||||
AgentProcessStatus string `json:"agent_process_status"` // 代理事务处理状态:not_agent-非代理订单,success-处理成功,failed-处理失败,pending-待处理
|
||||
}
|
||||
|
||||
type OrderSourceStatisticsItem struct {
|
||||
ProductName string `json:"product_name"` // 产品名称
|
||||
OrderCount int64 `json:"order_count"` // 订单数量
|
||||
}
|
||||
|
||||
type OrderStatisticsItem struct {
|
||||
Date string `json:"date"` // 日期
|
||||
Count int64 `json:"count"` // 订单数量
|
||||
Amount float64 `json:"amount"` // 订单金额
|
||||
}
|
||||
|
||||
type PaymentCheckReq struct {
|
||||
OrderNo string `json:"order_no" validate:"required"`
|
||||
}
|
||||
@@ -1665,7 +1841,7 @@ type PaymentCheckResp struct {
|
||||
type PaymentReq struct {
|
||||
Id string `json:"id"`
|
||||
PayMethod string `json:"pay_method"`
|
||||
PayType string `json:"pay_type" validate:"required,oneof=query agent_vip"`
|
||||
PayType string `json:"pay_type" validate:"required,oneof=query agent_vip agent_upgrade"`
|
||||
}
|
||||
|
||||
type PaymentResp struct {
|
||||
@@ -1680,6 +1856,7 @@ type PlatformUserListItem struct {
|
||||
Nickname string `json:"nickname"` // 昵称
|
||||
Info string `json:"info"` // 备注信息
|
||||
Inside int64 `json:"inside"` // 是否内部用户 1-是 0-否
|
||||
Disable int64 `json:"disable"` // 封禁状态 0-可用 1-禁用
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
UpdateTime string `json:"update_time"` // 更新时间
|
||||
}
|
||||
@@ -2043,6 +2220,7 @@ type GetAppVersionResp struct {
|
||||
}
|
||||
|
||||
type SendSmsReq struct {
|
||||
Mobile string `json:"mobile" validate:"required,mobile"`
|
||||
ActionType string `json:"actionType" validate:"required,oneof=login register query agentApply realName bindMobile"`
|
||||
Mobile string `json:"mobile" validate:"required,mobile"`
|
||||
CaptchaVerifyParam string `json:"captchaVerifyParam"`
|
||||
ActionType string `json:"actionType" validate:"omitempty,oneof=login register query agentApply realName bindMobile"`
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ func main() {
|
||||
defer server.Stop()
|
||||
|
||||
handler.RegisterHandlers(server, svcContext)
|
||||
|
||||
|
||||
// 自动注册API到数据库
|
||||
apiRegistry := service.NewApiRegistryService(svcContext.AdminApiModel)
|
||||
routes := server.Routes()
|
||||
@@ -70,7 +70,7 @@ func main() {
|
||||
} else {
|
||||
logx.Infof("API注册成功,共注册 %d 个路由", len(routes))
|
||||
}
|
||||
|
||||
|
||||
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
|
||||
server.Start()
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package model
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tydata-server/common/globalkey"
|
||||
"fmt"
|
||||
"tydata-server/common/globalkey"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/stores/cache"
|
||||
|
||||
@@ -27,7 +27,7 @@ var (
|
||||
agentCommissionDeductionRowsExpectAutoSet = strings.Join(stringx.Remove(agentCommissionDeductionFieldNames, "`id`", "`create_time`", "`update_time`"), ",")
|
||||
agentCommissionDeductionRowsWithPlaceHolder = strings.Join(stringx.Remove(agentCommissionDeductionFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?"
|
||||
|
||||
cacheHmAgentCommissionDeductionIdPrefix = "cache:tydata:agentCommissionDeduction:id:"
|
||||
cacheTydataAgentCommissionDeductionIdPrefix = "cache:tydata:agentCommissionDeduction:id:"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -55,18 +55,19 @@ type (
|
||||
}
|
||||
|
||||
AgentCommissionDeduction struct {
|
||||
Id int64 `db:"id"`
|
||||
AgentId int64 `db:"agent_id"`
|
||||
DeductedAgentId int64 `db:"deducted_agent_id"` // 被抽佣代理ID
|
||||
Amount float64 `db:"amount"`
|
||||
ProductId int64 `db:"product_id"` // 产品ID
|
||||
Type string `db:"type"`
|
||||
Status int64 `db:"status"` // 状态
|
||||
CreateTime time.Time `db:"create_time"`
|
||||
UpdateTime time.Time `db:"update_time"` // 更新时间
|
||||
DeleteTime sql.NullTime `db:"delete_time"` // 删除时间
|
||||
DelState int64 `db:"del_state"` // 删除状态
|
||||
Version int64 `db:"version"` // 版本号
|
||||
Id int64 `db:"id"`
|
||||
AgentId int64 `db:"agent_id"`
|
||||
DeductedAgentId int64 `db:"deducted_agent_id"` // 被抽佣代理ID
|
||||
Amount float64 `db:"amount"`
|
||||
ProductId int64 `db:"product_id"` // 产品ID
|
||||
OrderId sql.NullInt64 `db:"order_id"` // 关联订单ID
|
||||
Type string `db:"type"`
|
||||
Status int64 `db:"status"` // 状态
|
||||
CreateTime time.Time `db:"create_time"`
|
||||
UpdateTime time.Time `db:"update_time"` // 更新时间
|
||||
DeleteTime sql.NullTime `db:"delete_time"` // 删除时间
|
||||
DelState int64 `db:"del_state"` // 删除状态
|
||||
Version int64 `db:"version"` // 版本号
|
||||
}
|
||||
)
|
||||
|
||||
@@ -79,20 +80,20 @@ func newAgentCommissionDeductionModel(conn sqlx.SqlConn, c cache.CacheConf) *def
|
||||
|
||||
func (m *defaultAgentCommissionDeductionModel) Insert(ctx context.Context, session sqlx.Session, data *AgentCommissionDeduction) (sql.Result, error) {
|
||||
data.DelState = globalkey.DelStateNo
|
||||
hmAgentCommissionDeductionIdKey := fmt.Sprintf("%s%v", cacheHmAgentCommissionDeductionIdPrefix, data.Id)
|
||||
tydataAgentCommissionDeductionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentCommissionDeductionIdPrefix, data.Id)
|
||||
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, agentCommissionDeductionRowsExpectAutoSet)
|
||||
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, agentCommissionDeductionRowsExpectAutoSet)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version)
|
||||
return session.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version)
|
||||
}, hmAgentCommissionDeductionIdKey)
|
||||
return conn.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version)
|
||||
}, tydataAgentCommissionDeductionIdKey)
|
||||
}
|
||||
|
||||
func (m *defaultAgentCommissionDeductionModel) FindOne(ctx context.Context, id int64) (*AgentCommissionDeduction, error) {
|
||||
hmAgentCommissionDeductionIdKey := fmt.Sprintf("%s%v", cacheHmAgentCommissionDeductionIdPrefix, id)
|
||||
tydataAgentCommissionDeductionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentCommissionDeductionIdPrefix, id)
|
||||
var resp AgentCommissionDeduction
|
||||
err := m.QueryRowCtx(ctx, &resp, hmAgentCommissionDeductionIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error {
|
||||
err := m.QueryRowCtx(ctx, &resp, tydataAgentCommissionDeductionIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error {
|
||||
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentCommissionDeductionRows, m.table)
|
||||
return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo)
|
||||
})
|
||||
@@ -107,14 +108,14 @@ func (m *defaultAgentCommissionDeductionModel) FindOne(ctx context.Context, id i
|
||||
}
|
||||
|
||||
func (m *defaultAgentCommissionDeductionModel) Update(ctx context.Context, session sqlx.Session, data *AgentCommissionDeduction) (sql.Result, error) {
|
||||
hmAgentCommissionDeductionIdKey := fmt.Sprintf("%s%v", cacheHmAgentCommissionDeductionIdPrefix, data.Id)
|
||||
tydataAgentCommissionDeductionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentCommissionDeductionIdPrefix, data.Id)
|
||||
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, agentCommissionDeductionRowsWithPlaceHolder)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id)
|
||||
return session.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id)
|
||||
}, hmAgentCommissionDeductionIdKey)
|
||||
return conn.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id)
|
||||
}, tydataAgentCommissionDeductionIdKey)
|
||||
}
|
||||
|
||||
func (m *defaultAgentCommissionDeductionModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, data *AgentCommissionDeduction) error {
|
||||
@@ -125,14 +126,14 @@ func (m *defaultAgentCommissionDeductionModel) UpdateWithVersion(ctx context.Con
|
||||
var sqlResult sql.Result
|
||||
var err error
|
||||
|
||||
hmAgentCommissionDeductionIdKey := fmt.Sprintf("%s%v", cacheHmAgentCommissionDeductionIdPrefix, data.Id)
|
||||
tydataAgentCommissionDeductionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentCommissionDeductionIdPrefix, data.Id)
|
||||
sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, agentCommissionDeductionRowsWithPlaceHolder)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion)
|
||||
return session.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion)
|
||||
}, hmAgentCommissionDeductionIdKey)
|
||||
return conn.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion)
|
||||
}, tydataAgentCommissionDeductionIdKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -350,18 +351,18 @@ func (m *defaultAgentCommissionDeductionModel) SelectBuilder() squirrel.SelectBu
|
||||
return squirrel.Select().From(m.table)
|
||||
}
|
||||
func (m *defaultAgentCommissionDeductionModel) Delete(ctx context.Context, session sqlx.Session, id int64) error {
|
||||
hmAgentCommissionDeductionIdKey := fmt.Sprintf("%s%v", cacheHmAgentCommissionDeductionIdPrefix, id)
|
||||
tydataAgentCommissionDeductionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentCommissionDeductionIdPrefix, id)
|
||||
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, id)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, id)
|
||||
}, hmAgentCommissionDeductionIdKey)
|
||||
}, tydataAgentCommissionDeductionIdKey)
|
||||
return err
|
||||
}
|
||||
func (m *defaultAgentCommissionDeductionModel) formatPrimary(primary interface{}) string {
|
||||
return fmt.Sprintf("%s%v", cacheHmAgentCommissionDeductionIdPrefix, primary)
|
||||
return fmt.Sprintf("%s%v", cacheTydataAgentCommissionDeductionIdPrefix, primary)
|
||||
}
|
||||
func (m *defaultAgentCommissionDeductionModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error {
|
||||
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentCommissionDeductionRows, m.table)
|
||||
|
||||
@@ -10,8 +10,6 @@ import (
|
||||
|
||||
"time"
|
||||
|
||||
"tydata-server/common/globalkey"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/stores/builder"
|
||||
@@ -19,6 +17,7 @@ import (
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlc"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
"github.com/zeromicro/go-zero/core/stringx"
|
||||
"tydata-server/common/globalkey"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -27,7 +26,7 @@ var (
|
||||
agentCommissionRowsExpectAutoSet = strings.Join(stringx.Remove(agentCommissionFieldNames, "`id`", "`create_time`", "`update_time`"), ",")
|
||||
agentCommissionRowsWithPlaceHolder = strings.Join(stringx.Remove(agentCommissionFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?"
|
||||
|
||||
cacheHmAgentCommissionIdPrefix = "cache:tydata:agentCommission:id:"
|
||||
cacheTydataAgentCommissionIdPrefix = "cache:tydata:agentCommission:id:"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -55,17 +54,18 @@ type (
|
||||
}
|
||||
|
||||
AgentCommission struct {
|
||||
Id int64 `db:"id"`
|
||||
AgentId int64 `db:"agent_id"`
|
||||
OrderId int64 `db:"order_id"`
|
||||
Amount float64 `db:"amount"`
|
||||
ProductId int64 `db:"product_id"` // 产品ID
|
||||
Status int64 `db:"status"`
|
||||
CreateTime time.Time `db:"create_time"`
|
||||
UpdateTime time.Time `db:"update_time"` // 更新时间
|
||||
DeleteTime sql.NullTime `db:"delete_time"` // 删除时间
|
||||
DelState int64 `db:"del_state"` // 删除状态
|
||||
Version int64 `db:"version"` // 版本号
|
||||
Id int64 `db:"id"`
|
||||
AgentId int64 `db:"agent_id"`
|
||||
OrderId int64 `db:"order_id"`
|
||||
Amount float64 `db:"amount"`
|
||||
RefundedAmount float64 `db:"refunded_amount"` // 已退款佣金金额
|
||||
ProductId int64 `db:"product_id"` // 产品ID
|
||||
Status int64 `db:"status"`
|
||||
CreateTime time.Time `db:"create_time"`
|
||||
UpdateTime time.Time `db:"update_time"` // 更新时间
|
||||
DeleteTime sql.NullTime `db:"delete_time"` // 删除时间
|
||||
DelState int64 `db:"del_state"` // 删除状态
|
||||
Version int64 `db:"version"` // 版本号
|
||||
}
|
||||
)
|
||||
|
||||
@@ -78,20 +78,20 @@ func newAgentCommissionModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultAgent
|
||||
|
||||
func (m *defaultAgentCommissionModel) Insert(ctx context.Context, session sqlx.Session, data *AgentCommission) (sql.Result, error) {
|
||||
data.DelState = globalkey.DelStateNo
|
||||
hmAgentCommissionIdKey := fmt.Sprintf("%s%v", cacheHmAgentCommissionIdPrefix, data.Id)
|
||||
tydataAgentCommissionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentCommissionIdPrefix, data.Id)
|
||||
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?)", m.table, agentCommissionRowsExpectAutoSet)
|
||||
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, agentCommissionRowsExpectAutoSet)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, data.AgentId, data.OrderId, data.Amount, data.ProductId, data.Status, data.DeleteTime, data.DelState, data.Version)
|
||||
return session.ExecCtx(ctx, query, data.AgentId, data.OrderId, data.Amount, data.RefundedAmount, data.ProductId, data.Status, data.DeleteTime, data.DelState, data.Version)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, data.AgentId, data.OrderId, data.Amount, data.ProductId, data.Status, data.DeleteTime, data.DelState, data.Version)
|
||||
}, hmAgentCommissionIdKey)
|
||||
return conn.ExecCtx(ctx, query, data.AgentId, data.OrderId, data.Amount, data.RefundedAmount, data.ProductId, data.Status, data.DeleteTime, data.DelState, data.Version)
|
||||
}, tydataAgentCommissionIdKey)
|
||||
}
|
||||
|
||||
func (m *defaultAgentCommissionModel) FindOne(ctx context.Context, id int64) (*AgentCommission, error) {
|
||||
hmAgentCommissionIdKey := fmt.Sprintf("%s%v", cacheHmAgentCommissionIdPrefix, id)
|
||||
tydataAgentCommissionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentCommissionIdPrefix, id)
|
||||
var resp AgentCommission
|
||||
err := m.QueryRowCtx(ctx, &resp, hmAgentCommissionIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error {
|
||||
err := m.QueryRowCtx(ctx, &resp, tydataAgentCommissionIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error {
|
||||
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentCommissionRows, m.table)
|
||||
return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo)
|
||||
})
|
||||
@@ -106,14 +106,14 @@ func (m *defaultAgentCommissionModel) FindOne(ctx context.Context, id int64) (*A
|
||||
}
|
||||
|
||||
func (m *defaultAgentCommissionModel) Update(ctx context.Context, session sqlx.Session, data *AgentCommission) (sql.Result, error) {
|
||||
hmAgentCommissionIdKey := fmt.Sprintf("%s%v", cacheHmAgentCommissionIdPrefix, data.Id)
|
||||
tydataAgentCommissionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentCommissionIdPrefix, data.Id)
|
||||
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, agentCommissionRowsWithPlaceHolder)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, data.AgentId, data.OrderId, data.Amount, data.ProductId, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id)
|
||||
return session.ExecCtx(ctx, query, data.AgentId, data.OrderId, data.Amount, data.RefundedAmount, data.ProductId, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, data.AgentId, data.OrderId, data.Amount, data.ProductId, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id)
|
||||
}, hmAgentCommissionIdKey)
|
||||
return conn.ExecCtx(ctx, query, data.AgentId, data.OrderId, data.Amount, data.RefundedAmount, data.ProductId, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id)
|
||||
}, tydataAgentCommissionIdKey)
|
||||
}
|
||||
|
||||
func (m *defaultAgentCommissionModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, data *AgentCommission) error {
|
||||
@@ -124,14 +124,14 @@ func (m *defaultAgentCommissionModel) UpdateWithVersion(ctx context.Context, ses
|
||||
var sqlResult sql.Result
|
||||
var err error
|
||||
|
||||
hmAgentCommissionIdKey := fmt.Sprintf("%s%v", cacheHmAgentCommissionIdPrefix, data.Id)
|
||||
tydataAgentCommissionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentCommissionIdPrefix, data.Id)
|
||||
sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, agentCommissionRowsWithPlaceHolder)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, data.AgentId, data.OrderId, data.Amount, data.ProductId, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion)
|
||||
return session.ExecCtx(ctx, query, data.AgentId, data.OrderId, data.Amount, data.RefundedAmount, data.ProductId, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, data.AgentId, data.OrderId, data.Amount, data.ProductId, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion)
|
||||
}, hmAgentCommissionIdKey)
|
||||
return conn.ExecCtx(ctx, query, data.AgentId, data.OrderId, data.Amount, data.RefundedAmount, data.ProductId, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion)
|
||||
}, tydataAgentCommissionIdKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -349,18 +349,18 @@ func (m *defaultAgentCommissionModel) SelectBuilder() squirrel.SelectBuilder {
|
||||
return squirrel.Select().From(m.table)
|
||||
}
|
||||
func (m *defaultAgentCommissionModel) Delete(ctx context.Context, session sqlx.Session, id int64) error {
|
||||
hmAgentCommissionIdKey := fmt.Sprintf("%s%v", cacheHmAgentCommissionIdPrefix, id)
|
||||
tydataAgentCommissionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentCommissionIdPrefix, id)
|
||||
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, id)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, id)
|
||||
}, hmAgentCommissionIdKey)
|
||||
}, tydataAgentCommissionIdKey)
|
||||
return err
|
||||
}
|
||||
func (m *defaultAgentCommissionModel) formatPrimary(primary interface{}) string {
|
||||
return fmt.Sprintf("%s%v", cacheHmAgentCommissionIdPrefix, primary)
|
||||
return fmt.Sprintf("%s%v", cacheTydataAgentCommissionIdPrefix, primary)
|
||||
}
|
||||
func (m *defaultAgentCommissionModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error {
|
||||
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentCommissionRows, m.table)
|
||||
|
||||
@@ -27,9 +27,9 @@ var (
|
||||
agentRowsExpectAutoSet = strings.Join(stringx.Remove(agentFieldNames, "`id`", "`create_time`", "`update_time`"), ",")
|
||||
agentRowsWithPlaceHolder = strings.Join(stringx.Remove(agentFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?"
|
||||
|
||||
cacheHmAgentIdPrefix = "cache:tydata:agent:id:"
|
||||
cacheHmAgentMobilePrefix = "cache:tydata:agent:mobile:"
|
||||
cacheHmAgentUserIdPrefix = "cache:tydata:agent:userId:"
|
||||
cacheTydataAgentIdPrefix = "cache:tydata:agent:id:"
|
||||
cacheTydataAgentMobilePrefix = "cache:tydata:agent:mobile:"
|
||||
cacheTydataAgentUserIdPrefix = "cache:tydata:agent:userId:"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -83,22 +83,22 @@ func newAgentModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultAgentModel {
|
||||
|
||||
func (m *defaultAgentModel) Insert(ctx context.Context, session sqlx.Session, data *Agent) (sql.Result, error) {
|
||||
data.DelState = globalkey.DelStateNo
|
||||
hmAgentIdKey := fmt.Sprintf("%s%v", cacheHmAgentIdPrefix, data.Id)
|
||||
hmAgentMobileKey := fmt.Sprintf("%s%v", cacheHmAgentMobilePrefix, data.Mobile)
|
||||
hmAgentUserIdKey := fmt.Sprintf("%s%v", cacheHmAgentUserIdPrefix, data.UserId)
|
||||
tydataAgentIdKey := fmt.Sprintf("%s%v", cacheTydataAgentIdPrefix, data.Id)
|
||||
tydataAgentMobileKey := fmt.Sprintf("%s%v", cacheTydataAgentMobilePrefix, data.Mobile)
|
||||
tydataAgentUserIdKey := fmt.Sprintf("%s%v", cacheTydataAgentUserIdPrefix, data.UserId)
|
||||
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, agentRowsExpectAutoSet)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, data.UserId, data.LevelName, data.Region, data.Mobile, data.WechatId, data.MembershipExpiryTime, data.DeleteTime, data.DelState, data.Version)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, data.UserId, data.LevelName, data.Region, data.Mobile, data.WechatId, data.MembershipExpiryTime, data.DeleteTime, data.DelState, data.Version)
|
||||
}, hmAgentIdKey, hmAgentMobileKey, hmAgentUserIdKey)
|
||||
}, tydataAgentIdKey, tydataAgentMobileKey, tydataAgentUserIdKey)
|
||||
}
|
||||
|
||||
func (m *defaultAgentModel) FindOne(ctx context.Context, id int64) (*Agent, error) {
|
||||
hmAgentIdKey := fmt.Sprintf("%s%v", cacheHmAgentIdPrefix, id)
|
||||
tydataAgentIdKey := fmt.Sprintf("%s%v", cacheTydataAgentIdPrefix, id)
|
||||
var resp Agent
|
||||
err := m.QueryRowCtx(ctx, &resp, hmAgentIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error {
|
||||
err := m.QueryRowCtx(ctx, &resp, tydataAgentIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error {
|
||||
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentRows, m.table)
|
||||
return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo)
|
||||
})
|
||||
@@ -113,9 +113,9 @@ func (m *defaultAgentModel) FindOne(ctx context.Context, id int64) (*Agent, erro
|
||||
}
|
||||
|
||||
func (m *defaultAgentModel) FindOneByMobile(ctx context.Context, mobile string) (*Agent, error) {
|
||||
hmAgentMobileKey := fmt.Sprintf("%s%v", cacheHmAgentMobilePrefix, mobile)
|
||||
tydataAgentMobileKey := fmt.Sprintf("%s%v", cacheTydataAgentMobilePrefix, mobile)
|
||||
var resp Agent
|
||||
err := m.QueryRowIndexCtx(ctx, &resp, hmAgentMobileKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
||||
err := m.QueryRowIndexCtx(ctx, &resp, tydataAgentMobileKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
||||
query := fmt.Sprintf("select %s from %s where `mobile` = ? and del_state = ? limit 1", agentRows, m.table)
|
||||
if err := conn.QueryRowCtx(ctx, &resp, query, mobile, globalkey.DelStateNo); err != nil {
|
||||
return nil, err
|
||||
@@ -133,9 +133,9 @@ func (m *defaultAgentModel) FindOneByMobile(ctx context.Context, mobile string)
|
||||
}
|
||||
|
||||
func (m *defaultAgentModel) FindOneByUserId(ctx context.Context, userId int64) (*Agent, error) {
|
||||
hmAgentUserIdKey := fmt.Sprintf("%s%v", cacheHmAgentUserIdPrefix, userId)
|
||||
tydataAgentUserIdKey := fmt.Sprintf("%s%v", cacheTydataAgentUserIdPrefix, userId)
|
||||
var resp Agent
|
||||
err := m.QueryRowIndexCtx(ctx, &resp, hmAgentUserIdKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
||||
err := m.QueryRowIndexCtx(ctx, &resp, tydataAgentUserIdKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
||||
query := fmt.Sprintf("select %s from %s where `user_id` = ? and del_state = ? limit 1", agentRows, m.table)
|
||||
if err := conn.QueryRowCtx(ctx, &resp, query, userId, globalkey.DelStateNo); err != nil {
|
||||
return nil, err
|
||||
@@ -157,16 +157,16 @@ func (m *defaultAgentModel) Update(ctx context.Context, session sqlx.Session, ne
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hmAgentIdKey := fmt.Sprintf("%s%v", cacheHmAgentIdPrefix, data.Id)
|
||||
hmAgentMobileKey := fmt.Sprintf("%s%v", cacheHmAgentMobilePrefix, data.Mobile)
|
||||
hmAgentUserIdKey := fmt.Sprintf("%s%v", cacheHmAgentUserIdPrefix, data.UserId)
|
||||
tydataAgentIdKey := fmt.Sprintf("%s%v", cacheTydataAgentIdPrefix, data.Id)
|
||||
tydataAgentMobileKey := fmt.Sprintf("%s%v", cacheTydataAgentMobilePrefix, data.Mobile)
|
||||
tydataAgentUserIdKey := fmt.Sprintf("%s%v", cacheTydataAgentUserIdPrefix, data.UserId)
|
||||
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, agentRowsWithPlaceHolder)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, newData.UserId, newData.LevelName, newData.Region, newData.Mobile, newData.WechatId, newData.MembershipExpiryTime, newData.DeleteTime, newData.DelState, newData.Version, newData.Id)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, newData.UserId, newData.LevelName, newData.Region, newData.Mobile, newData.WechatId, newData.MembershipExpiryTime, newData.DeleteTime, newData.DelState, newData.Version, newData.Id)
|
||||
}, hmAgentIdKey, hmAgentMobileKey, hmAgentUserIdKey)
|
||||
}, tydataAgentIdKey, tydataAgentMobileKey, tydataAgentUserIdKey)
|
||||
}
|
||||
|
||||
func (m *defaultAgentModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *Agent) error {
|
||||
@@ -181,16 +181,16 @@ func (m *defaultAgentModel) UpdateWithVersion(ctx context.Context, session sqlx.
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hmAgentIdKey := fmt.Sprintf("%s%v", cacheHmAgentIdPrefix, data.Id)
|
||||
hmAgentMobileKey := fmt.Sprintf("%s%v", cacheHmAgentMobilePrefix, data.Mobile)
|
||||
hmAgentUserIdKey := fmt.Sprintf("%s%v", cacheHmAgentUserIdPrefix, data.UserId)
|
||||
tydataAgentIdKey := fmt.Sprintf("%s%v", cacheTydataAgentIdPrefix, data.Id)
|
||||
tydataAgentMobileKey := fmt.Sprintf("%s%v", cacheTydataAgentMobilePrefix, data.Mobile)
|
||||
tydataAgentUserIdKey := fmt.Sprintf("%s%v", cacheTydataAgentUserIdPrefix, data.UserId)
|
||||
sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, agentRowsWithPlaceHolder)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, newData.UserId, newData.LevelName, newData.Region, newData.Mobile, newData.WechatId, newData.MembershipExpiryTime, newData.DeleteTime, newData.DelState, newData.Version, newData.Id, oldVersion)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, newData.UserId, newData.LevelName, newData.Region, newData.Mobile, newData.WechatId, newData.MembershipExpiryTime, newData.DeleteTime, newData.DelState, newData.Version, newData.Id, oldVersion)
|
||||
}, hmAgentIdKey, hmAgentMobileKey, hmAgentUserIdKey)
|
||||
}, tydataAgentIdKey, tydataAgentMobileKey, tydataAgentUserIdKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -413,20 +413,20 @@ func (m *defaultAgentModel) Delete(ctx context.Context, session sqlx.Session, id
|
||||
return err
|
||||
}
|
||||
|
||||
hmAgentIdKey := fmt.Sprintf("%s%v", cacheHmAgentIdPrefix, id)
|
||||
hmAgentMobileKey := fmt.Sprintf("%s%v", cacheHmAgentMobilePrefix, data.Mobile)
|
||||
hmAgentUserIdKey := fmt.Sprintf("%s%v", cacheHmAgentUserIdPrefix, data.UserId)
|
||||
tydataAgentIdKey := fmt.Sprintf("%s%v", cacheTydataAgentIdPrefix, id)
|
||||
tydataAgentMobileKey := fmt.Sprintf("%s%v", cacheTydataAgentMobilePrefix, data.Mobile)
|
||||
tydataAgentUserIdKey := fmt.Sprintf("%s%v", cacheTydataAgentUserIdPrefix, data.UserId)
|
||||
_, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, id)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, id)
|
||||
}, hmAgentIdKey, hmAgentMobileKey, hmAgentUserIdKey)
|
||||
}, tydataAgentIdKey, tydataAgentMobileKey, tydataAgentUserIdKey)
|
||||
return err
|
||||
}
|
||||
func (m *defaultAgentModel) formatPrimary(primary interface{}) string {
|
||||
return fmt.Sprintf("%s%v", cacheHmAgentIdPrefix, primary)
|
||||
return fmt.Sprintf("%s%v", cacheTydataAgentIdPrefix, primary)
|
||||
}
|
||||
func (m *defaultAgentModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error {
|
||||
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentRows, m.table)
|
||||
|
||||
@@ -27,7 +27,7 @@ var (
|
||||
agentPlatformDeductionRowsExpectAutoSet = strings.Join(stringx.Remove(agentPlatformDeductionFieldNames, "`id`", "`create_time`", "`update_time`"), ",")
|
||||
agentPlatformDeductionRowsWithPlaceHolder = strings.Join(stringx.Remove(agentPlatformDeductionFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?"
|
||||
|
||||
cacheHmAgentPlatformDeductionIdPrefix = "cache:tydata:agentPlatformDeduction:id:"
|
||||
cacheTydataAgentPlatformDeductionIdPrefix = "cache:tydata:agentPlatformDeduction:id:"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -56,6 +56,7 @@ type (
|
||||
|
||||
AgentPlatformDeduction struct {
|
||||
Id int64 `db:"id"`
|
||||
OrderId int64 `db:"order_id"` // 订单ID
|
||||
AgentId int64 `db:"agent_id"` // 被抽佣代理ID
|
||||
Amount float64 `db:"amount"`
|
||||
Type string `db:"type"`
|
||||
@@ -77,20 +78,20 @@ func newAgentPlatformDeductionModel(conn sqlx.SqlConn, c cache.CacheConf) *defau
|
||||
|
||||
func (m *defaultAgentPlatformDeductionModel) Insert(ctx context.Context, session sqlx.Session, data *AgentPlatformDeduction) (sql.Result, error) {
|
||||
data.DelState = globalkey.DelStateNo
|
||||
hmAgentPlatformDeductionIdKey := fmt.Sprintf("%s%v", cacheHmAgentPlatformDeductionIdPrefix, data.Id)
|
||||
tydataAgentPlatformDeductionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentPlatformDeductionIdPrefix, data.Id)
|
||||
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?)", m.table, agentPlatformDeductionRowsExpectAutoSet)
|
||||
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?)", m.table, agentPlatformDeductionRowsExpectAutoSet)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, data.AgentId, data.Amount, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version)
|
||||
return session.ExecCtx(ctx, query, data.OrderId, data.AgentId, data.Amount, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, data.AgentId, data.Amount, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version)
|
||||
}, hmAgentPlatformDeductionIdKey)
|
||||
return conn.ExecCtx(ctx, query, data.OrderId, data.AgentId, data.Amount, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version)
|
||||
}, tydataAgentPlatformDeductionIdKey)
|
||||
}
|
||||
|
||||
func (m *defaultAgentPlatformDeductionModel) FindOne(ctx context.Context, id int64) (*AgentPlatformDeduction, error) {
|
||||
hmAgentPlatformDeductionIdKey := fmt.Sprintf("%s%v", cacheHmAgentPlatformDeductionIdPrefix, id)
|
||||
tydataAgentPlatformDeductionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentPlatformDeductionIdPrefix, id)
|
||||
var resp AgentPlatformDeduction
|
||||
err := m.QueryRowCtx(ctx, &resp, hmAgentPlatformDeductionIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error {
|
||||
err := m.QueryRowCtx(ctx, &resp, tydataAgentPlatformDeductionIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error {
|
||||
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentPlatformDeductionRows, m.table)
|
||||
return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo)
|
||||
})
|
||||
@@ -105,14 +106,14 @@ func (m *defaultAgentPlatformDeductionModel) FindOne(ctx context.Context, id int
|
||||
}
|
||||
|
||||
func (m *defaultAgentPlatformDeductionModel) Update(ctx context.Context, session sqlx.Session, data *AgentPlatformDeduction) (sql.Result, error) {
|
||||
hmAgentPlatformDeductionIdKey := fmt.Sprintf("%s%v", cacheHmAgentPlatformDeductionIdPrefix, data.Id)
|
||||
tydataAgentPlatformDeductionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentPlatformDeductionIdPrefix, data.Id)
|
||||
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, agentPlatformDeductionRowsWithPlaceHolder)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, data.AgentId, data.Amount, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id)
|
||||
return session.ExecCtx(ctx, query, data.OrderId, data.AgentId, data.Amount, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, data.AgentId, data.Amount, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id)
|
||||
}, hmAgentPlatformDeductionIdKey)
|
||||
return conn.ExecCtx(ctx, query, data.OrderId, data.AgentId, data.Amount, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id)
|
||||
}, tydataAgentPlatformDeductionIdKey)
|
||||
}
|
||||
|
||||
func (m *defaultAgentPlatformDeductionModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, data *AgentPlatformDeduction) error {
|
||||
@@ -123,14 +124,14 @@ func (m *defaultAgentPlatformDeductionModel) UpdateWithVersion(ctx context.Conte
|
||||
var sqlResult sql.Result
|
||||
var err error
|
||||
|
||||
hmAgentPlatformDeductionIdKey := fmt.Sprintf("%s%v", cacheHmAgentPlatformDeductionIdPrefix, data.Id)
|
||||
tydataAgentPlatformDeductionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentPlatformDeductionIdPrefix, data.Id)
|
||||
sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, agentPlatformDeductionRowsWithPlaceHolder)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, data.AgentId, data.Amount, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion)
|
||||
return session.ExecCtx(ctx, query, data.OrderId, data.AgentId, data.Amount, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, data.AgentId, data.Amount, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion)
|
||||
}, hmAgentPlatformDeductionIdKey)
|
||||
return conn.ExecCtx(ctx, query, data.OrderId, data.AgentId, data.Amount, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion)
|
||||
}, tydataAgentPlatformDeductionIdKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -348,18 +349,18 @@ func (m *defaultAgentPlatformDeductionModel) SelectBuilder() squirrel.SelectBuil
|
||||
return squirrel.Select().From(m.table)
|
||||
}
|
||||
func (m *defaultAgentPlatformDeductionModel) Delete(ctx context.Context, session sqlx.Session, id int64) error {
|
||||
hmAgentPlatformDeductionIdKey := fmt.Sprintf("%s%v", cacheHmAgentPlatformDeductionIdPrefix, id)
|
||||
tydataAgentPlatformDeductionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentPlatformDeductionIdPrefix, id)
|
||||
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, id)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, id)
|
||||
}, hmAgentPlatformDeductionIdKey)
|
||||
}, tydataAgentPlatformDeductionIdKey)
|
||||
return err
|
||||
}
|
||||
func (m *defaultAgentPlatformDeductionModel) formatPrimary(primary interface{}) string {
|
||||
return fmt.Sprintf("%s%v", cacheHmAgentPlatformDeductionIdPrefix, primary)
|
||||
return fmt.Sprintf("%s%v", cacheTydataAgentPlatformDeductionIdPrefix, primary)
|
||||
}
|
||||
func (m *defaultAgentPlatformDeductionModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error {
|
||||
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentPlatformDeductionRows, m.table)
|
||||
|
||||
27
app/main/model/agentWalletTransactionModel.go
Normal file
27
app/main/model/agentWalletTransactionModel.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/zeromicro/go-zero/core/stores/cache"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
)
|
||||
|
||||
var _ AgentWalletTransactionModel = (*customAgentWalletTransactionModel)(nil)
|
||||
|
||||
type (
|
||||
// AgentWalletTransactionModel is an interface to be customized, add more methods here,
|
||||
// and implement the added methods in customAgentWalletTransactionModel.
|
||||
AgentWalletTransactionModel interface {
|
||||
agentWalletTransactionModel
|
||||
}
|
||||
|
||||
customAgentWalletTransactionModel struct {
|
||||
*defaultAgentWalletTransactionModel
|
||||
}
|
||||
)
|
||||
|
||||
// NewAgentWalletTransactionModel returns a model for the database table.
|
||||
func NewAgentWalletTransactionModel(conn sqlx.SqlConn, c cache.CacheConf) AgentWalletTransactionModel {
|
||||
return &customAgentWalletTransactionModel{
|
||||
defaultAgentWalletTransactionModel: newAgentWalletTransactionModel(conn, c),
|
||||
}
|
||||
}
|
||||
377
app/main/model/agentWalletTransactionModel_gen.go
Normal file
377
app/main/model/agentWalletTransactionModel_gen.go
Normal file
@@ -0,0 +1,377 @@
|
||||
// Code generated by goctl. DO NOT EDIT!
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"time"
|
||||
|
||||
"tydata-server/common/globalkey"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/stores/builder"
|
||||
"github.com/zeromicro/go-zero/core/stores/cache"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlc"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
"github.com/zeromicro/go-zero/core/stringx"
|
||||
)
|
||||
|
||||
var (
|
||||
agentWalletTransactionFieldNames = builder.RawFieldNames(&AgentWalletTransaction{})
|
||||
agentWalletTransactionRows = strings.Join(agentWalletTransactionFieldNames, ",")
|
||||
agentWalletTransactionRowsExpectAutoSet = strings.Join(stringx.Remove(agentWalletTransactionFieldNames, "`id`", "`create_time`", "`update_time`"), ",")
|
||||
agentWalletTransactionRowsWithPlaceHolder = strings.Join(stringx.Remove(agentWalletTransactionFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?"
|
||||
|
||||
cacheTydataAgentWalletTransactionIdPrefix = "cache:tydata:agentWalletTransaction:id:"
|
||||
)
|
||||
|
||||
type (
|
||||
agentWalletTransactionModel interface {
|
||||
Insert(ctx context.Context, session sqlx.Session, data *AgentWalletTransaction) (sql.Result, error)
|
||||
FindOne(ctx context.Context, id int64) (*AgentWalletTransaction, error)
|
||||
Update(ctx context.Context, session sqlx.Session, data *AgentWalletTransaction) (sql.Result, error)
|
||||
UpdateWithVersion(ctx context.Context, session sqlx.Session, data *AgentWalletTransaction) error
|
||||
Trans(ctx context.Context, fn func(context context.Context, session sqlx.Session) error) error
|
||||
SelectBuilder() squirrel.SelectBuilder
|
||||
DeleteSoft(ctx context.Context, session sqlx.Session, data *AgentWalletTransaction) error
|
||||
FindSum(ctx context.Context, sumBuilder squirrel.SelectBuilder, field string) (float64, error)
|
||||
FindCount(ctx context.Context, countBuilder squirrel.SelectBuilder, field string) (int64, error)
|
||||
FindAll(ctx context.Context, rowBuilder squirrel.SelectBuilder, orderBy string) ([]*AgentWalletTransaction, error)
|
||||
FindPageListByPage(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*AgentWalletTransaction, error)
|
||||
FindPageListByPageWithTotal(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*AgentWalletTransaction, int64, error)
|
||||
FindPageListByIdDESC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*AgentWalletTransaction, error)
|
||||
FindPageListByIdASC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*AgentWalletTransaction, error)
|
||||
Delete(ctx context.Context, session sqlx.Session, id int64) error
|
||||
}
|
||||
|
||||
defaultAgentWalletTransactionModel struct {
|
||||
sqlc.CachedConn
|
||||
table string
|
||||
}
|
||||
|
||||
AgentWalletTransaction struct {
|
||||
Id int64 `db:"id"`
|
||||
CreateTime time.Time `db:"create_time"`
|
||||
UpdateTime time.Time `db:"update_time"`
|
||||
DeleteTime sql.NullTime `db:"delete_time"` // 删除时间
|
||||
DelState int64 `db:"del_state"`
|
||||
Version int64 `db:"version"` // 版本号
|
||||
AgentId int64 `db:"agent_id"` // 代理ID
|
||||
TransactionType string `db:"transaction_type"` // 交易类型:commission(佣金收入)、withdraw(提现)、freeze(冻结)、unfreeze(解冻)、reward(奖励)、refund(退款)、adjust(调整)等
|
||||
Amount float64 `db:"amount"` // 变动金额(正数为增加,负数为减少)
|
||||
BalanceBefore float64 `db:"balance_before"` // 变动前余额
|
||||
BalanceAfter float64 `db:"balance_after"` // 变动后余额
|
||||
FrozenBalanceBefore float64 `db:"frozen_balance_before"` // 变动前冻结余额
|
||||
FrozenBalanceAfter float64 `db:"frozen_balance_after"` // 变动后冻结余额
|
||||
TransactionId sql.NullString `db:"transaction_id"` // 关联交易ID(订单号、提现申请号等)
|
||||
RelatedUserId sql.NullInt64 `db:"related_user_id"` // 关联用户ID(如佣金来源用户)
|
||||
Remark sql.NullString `db:"remark"` // 备注说明
|
||||
}
|
||||
)
|
||||
|
||||
func newAgentWalletTransactionModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultAgentWalletTransactionModel {
|
||||
return &defaultAgentWalletTransactionModel{
|
||||
CachedConn: sqlc.NewConn(conn, c),
|
||||
table: "`agent_wallet_transaction`",
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultAgentWalletTransactionModel) Insert(ctx context.Context, session sqlx.Session, data *AgentWalletTransaction) (sql.Result, error) {
|
||||
data.DelState = globalkey.DelStateNo
|
||||
tydataAgentWalletTransactionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentWalletTransactionIdPrefix, data.Id)
|
||||
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, agentWalletTransactionRowsExpectAutoSet)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.AgentId, data.TransactionType, data.Amount, data.BalanceBefore, data.BalanceAfter, data.FrozenBalanceBefore, data.FrozenBalanceAfter, data.TransactionId, data.RelatedUserId, data.Remark)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.AgentId, data.TransactionType, data.Amount, data.BalanceBefore, data.BalanceAfter, data.FrozenBalanceBefore, data.FrozenBalanceAfter, data.TransactionId, data.RelatedUserId, data.Remark)
|
||||
}, tydataAgentWalletTransactionIdKey)
|
||||
}
|
||||
|
||||
func (m *defaultAgentWalletTransactionModel) FindOne(ctx context.Context, id int64) (*AgentWalletTransaction, error) {
|
||||
tydataAgentWalletTransactionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentWalletTransactionIdPrefix, id)
|
||||
var resp AgentWalletTransaction
|
||||
err := m.QueryRowCtx(ctx, &resp, tydataAgentWalletTransactionIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error {
|
||||
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentWalletTransactionRows, m.table)
|
||||
return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo)
|
||||
})
|
||||
switch err {
|
||||
case nil:
|
||||
return &resp, nil
|
||||
case sqlc.ErrNotFound:
|
||||
return nil, ErrNotFound
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultAgentWalletTransactionModel) Update(ctx context.Context, session sqlx.Session, data *AgentWalletTransaction) (sql.Result, error) {
|
||||
tydataAgentWalletTransactionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentWalletTransactionIdPrefix, data.Id)
|
||||
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, agentWalletTransactionRowsWithPlaceHolder)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.AgentId, data.TransactionType, data.Amount, data.BalanceBefore, data.BalanceAfter, data.FrozenBalanceBefore, data.FrozenBalanceAfter, data.TransactionId, data.RelatedUserId, data.Remark, data.Id)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.AgentId, data.TransactionType, data.Amount, data.BalanceBefore, data.BalanceAfter, data.FrozenBalanceBefore, data.FrozenBalanceAfter, data.TransactionId, data.RelatedUserId, data.Remark, data.Id)
|
||||
}, tydataAgentWalletTransactionIdKey)
|
||||
}
|
||||
|
||||
func (m *defaultAgentWalletTransactionModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, data *AgentWalletTransaction) error {
|
||||
|
||||
oldVersion := data.Version
|
||||
data.Version += 1
|
||||
|
||||
var sqlResult sql.Result
|
||||
var err error
|
||||
|
||||
tydataAgentWalletTransactionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentWalletTransactionIdPrefix, data.Id)
|
||||
sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, agentWalletTransactionRowsWithPlaceHolder)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.AgentId, data.TransactionType, data.Amount, data.BalanceBefore, data.BalanceAfter, data.FrozenBalanceBefore, data.FrozenBalanceAfter, data.TransactionId, data.RelatedUserId, data.Remark, data.Id, oldVersion)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.AgentId, data.TransactionType, data.Amount, data.BalanceBefore, data.BalanceAfter, data.FrozenBalanceBefore, data.FrozenBalanceAfter, data.TransactionId, data.RelatedUserId, data.Remark, data.Id, oldVersion)
|
||||
}, tydataAgentWalletTransactionIdKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updateCount, err := sqlResult.RowsAffected()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if updateCount == 0 {
|
||||
return ErrNoRowsUpdate
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *defaultAgentWalletTransactionModel) DeleteSoft(ctx context.Context, session sqlx.Session, data *AgentWalletTransaction) error {
|
||||
data.DelState = globalkey.DelStateYes
|
||||
data.DeleteTime = sql.NullTime{Time: time.Now(), Valid: true}
|
||||
if err := m.UpdateWithVersion(ctx, session, data); err != nil {
|
||||
return errors.Wrapf(errors.New("delete soft failed "), "AgentWalletTransactionModel delete err : %+v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *defaultAgentWalletTransactionModel) FindSum(ctx context.Context, builder squirrel.SelectBuilder, field string) (float64, error) {
|
||||
|
||||
if len(field) == 0 {
|
||||
return 0, errors.Wrapf(errors.New("FindSum Least One Field"), "FindSum Least One Field")
|
||||
}
|
||||
|
||||
builder = builder.Columns("IFNULL(SUM(" + field + "),0)")
|
||||
|
||||
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var resp float64
|
||||
err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...)
|
||||
switch err {
|
||||
case nil:
|
||||
return resp, nil
|
||||
default:
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultAgentWalletTransactionModel) FindCount(ctx context.Context, builder squirrel.SelectBuilder, field string) (int64, error) {
|
||||
|
||||
if len(field) == 0 {
|
||||
return 0, errors.Wrapf(errors.New("FindCount Least One Field"), "FindCount Least One Field")
|
||||
}
|
||||
|
||||
builder = builder.Columns("COUNT(" + field + ")")
|
||||
|
||||
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var resp int64
|
||||
err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...)
|
||||
switch err {
|
||||
case nil:
|
||||
return resp, nil
|
||||
default:
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultAgentWalletTransactionModel) FindAll(ctx context.Context, builder squirrel.SelectBuilder, orderBy string) ([]*AgentWalletTransaction, error) {
|
||||
|
||||
builder = builder.Columns(agentWalletTransactionRows)
|
||||
|
||||
if orderBy == "" {
|
||||
builder = builder.OrderBy("id DESC")
|
||||
} else {
|
||||
builder = builder.OrderBy(orderBy)
|
||||
}
|
||||
|
||||
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp []*AgentWalletTransaction
|
||||
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
|
||||
switch err {
|
||||
case nil:
|
||||
return resp, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultAgentWalletTransactionModel) FindPageListByPage(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*AgentWalletTransaction, error) {
|
||||
|
||||
builder = builder.Columns(agentWalletTransactionRows)
|
||||
|
||||
if orderBy == "" {
|
||||
builder = builder.OrderBy("id DESC")
|
||||
} else {
|
||||
builder = builder.OrderBy(orderBy)
|
||||
}
|
||||
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
offset := (page - 1) * pageSize
|
||||
|
||||
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp []*AgentWalletTransaction
|
||||
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
|
||||
switch err {
|
||||
case nil:
|
||||
return resp, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultAgentWalletTransactionModel) FindPageListByPageWithTotal(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*AgentWalletTransaction, int64, error) {
|
||||
|
||||
total, err := m.FindCount(ctx, builder, "id")
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
builder = builder.Columns(agentWalletTransactionRows)
|
||||
|
||||
if orderBy == "" {
|
||||
builder = builder.OrderBy("id DESC")
|
||||
} else {
|
||||
builder = builder.OrderBy(orderBy)
|
||||
}
|
||||
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
offset := (page - 1) * pageSize
|
||||
|
||||
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql()
|
||||
if err != nil {
|
||||
return nil, total, err
|
||||
}
|
||||
|
||||
var resp []*AgentWalletTransaction
|
||||
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
|
||||
switch err {
|
||||
case nil:
|
||||
return resp, total, nil
|
||||
default:
|
||||
return nil, total, err
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultAgentWalletTransactionModel) FindPageListByIdDESC(ctx context.Context, builder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*AgentWalletTransaction, error) {
|
||||
|
||||
builder = builder.Columns(agentWalletTransactionRows)
|
||||
|
||||
if preMinId > 0 {
|
||||
builder = builder.Where(" id < ? ", preMinId)
|
||||
}
|
||||
|
||||
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id DESC").Limit(uint64(pageSize)).ToSql()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp []*AgentWalletTransaction
|
||||
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
|
||||
switch err {
|
||||
case nil:
|
||||
return resp, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultAgentWalletTransactionModel) FindPageListByIdASC(ctx context.Context, builder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*AgentWalletTransaction, error) {
|
||||
|
||||
builder = builder.Columns(agentWalletTransactionRows)
|
||||
|
||||
if preMaxId > 0 {
|
||||
builder = builder.Where(" id > ? ", preMaxId)
|
||||
}
|
||||
|
||||
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id ASC").Limit(uint64(pageSize)).ToSql()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp []*AgentWalletTransaction
|
||||
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
|
||||
switch err {
|
||||
case nil:
|
||||
return resp, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultAgentWalletTransactionModel) Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error {
|
||||
|
||||
return m.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||
return fn(ctx, session)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func (m *defaultAgentWalletTransactionModel) SelectBuilder() squirrel.SelectBuilder {
|
||||
return squirrel.Select().From(m.table)
|
||||
}
|
||||
func (m *defaultAgentWalletTransactionModel) Delete(ctx context.Context, session sqlx.Session, id int64) error {
|
||||
tydataAgentWalletTransactionIdKey := fmt.Sprintf("%s%v", cacheTydataAgentWalletTransactionIdPrefix, id)
|
||||
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, id)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, id)
|
||||
}, tydataAgentWalletTransactionIdKey)
|
||||
return err
|
||||
}
|
||||
func (m *defaultAgentWalletTransactionModel) formatPrimary(primary interface{}) string {
|
||||
return fmt.Sprintf("%s%v", cacheTydataAgentWalletTransactionIdPrefix, primary)
|
||||
}
|
||||
func (m *defaultAgentWalletTransactionModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error {
|
||||
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentWalletTransactionRows, m.table)
|
||||
return conn.QueryRowCtx(ctx, v, query, primary, globalkey.DelStateNo)
|
||||
}
|
||||
|
||||
func (m *defaultAgentWalletTransactionModel) tableName() string {
|
||||
return m.table
|
||||
}
|
||||
@@ -10,8 +10,6 @@ import (
|
||||
|
||||
"time"
|
||||
|
||||
"tydata-server/common/globalkey"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/stores/builder"
|
||||
@@ -19,6 +17,7 @@ import (
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlc"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
"github.com/zeromicro/go-zero/core/stringx"
|
||||
"tydata-server/common/globalkey"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -27,8 +26,8 @@ var (
|
||||
orderRowsExpectAutoSet = strings.Join(stringx.Remove(orderFieldNames, "`id`", "`create_time`", "`update_time`"), ",")
|
||||
orderRowsWithPlaceHolder = strings.Join(stringx.Remove(orderFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?"
|
||||
|
||||
cacheHmOrderIdPrefix = "cache:tydata:order:id:"
|
||||
cacheHmOrderOrderNoPrefix = "cache:tydata:order:orderNo:"
|
||||
cacheTydataOrderIdPrefix = "cache:tydata:order:id:"
|
||||
cacheTydataOrderOrderNoPrefix = "cache:tydata:order:orderNo:"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -74,6 +73,7 @@ type (
|
||||
RefundTime sql.NullTime `db:"refund_time"` // 退款时间
|
||||
CloseTime sql.NullTime `db:"close_time"` // 订单关闭时间
|
||||
DeleteTime sql.NullTime `db:"delete_time"` // 删除时间
|
||||
SalesCost float64 `db:"sales_cost"` // 销售成本
|
||||
}
|
||||
)
|
||||
|
||||
@@ -86,21 +86,21 @@ func newOrderModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultOrderModel {
|
||||
|
||||
func (m *defaultOrderModel) Insert(ctx context.Context, session sqlx.Session, data *Order) (sql.Result, error) {
|
||||
data.DelState = globalkey.DelStateNo
|
||||
hmOrderIdKey := fmt.Sprintf("%s%v", cacheHmOrderIdPrefix, data.Id)
|
||||
hmOrderOrderNoKey := fmt.Sprintf("%s%v", cacheHmOrderOrderNoPrefix, data.OrderNo)
|
||||
tydataOrderIdKey := fmt.Sprintf("%s%v", cacheTydataOrderIdPrefix, data.Id)
|
||||
tydataOrderOrderNoKey := fmt.Sprintf("%s%v", cacheTydataOrderOrderNoPrefix, data.OrderNo)
|
||||
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, orderRowsExpectAutoSet)
|
||||
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, orderRowsExpectAutoSet)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, data.OrderNo, data.UserId, data.ProductId, data.PaymentPlatform, data.PaymentScene, data.PlatformOrderId, data.Amount, data.Status, data.DelState, data.Version, data.PayTime, data.RefundTime, data.CloseTime, data.DeleteTime)
|
||||
return session.ExecCtx(ctx, query, data.OrderNo, data.UserId, data.ProductId, data.PaymentPlatform, data.PaymentScene, data.PlatformOrderId, data.Amount, data.Status, data.DelState, data.Version, data.PayTime, data.RefundTime, data.CloseTime, data.DeleteTime, data.SalesCost)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, data.OrderNo, data.UserId, data.ProductId, data.PaymentPlatform, data.PaymentScene, data.PlatformOrderId, data.Amount, data.Status, data.DelState, data.Version, data.PayTime, data.RefundTime, data.CloseTime, data.DeleteTime)
|
||||
}, hmOrderIdKey, hmOrderOrderNoKey)
|
||||
return conn.ExecCtx(ctx, query, data.OrderNo, data.UserId, data.ProductId, data.PaymentPlatform, data.PaymentScene, data.PlatformOrderId, data.Amount, data.Status, data.DelState, data.Version, data.PayTime, data.RefundTime, data.CloseTime, data.DeleteTime, data.SalesCost)
|
||||
}, tydataOrderIdKey, tydataOrderOrderNoKey)
|
||||
}
|
||||
|
||||
func (m *defaultOrderModel) FindOne(ctx context.Context, id int64) (*Order, error) {
|
||||
hmOrderIdKey := fmt.Sprintf("%s%v", cacheHmOrderIdPrefix, id)
|
||||
tydataOrderIdKey := fmt.Sprintf("%s%v", cacheTydataOrderIdPrefix, id)
|
||||
var resp Order
|
||||
err := m.QueryRowCtx(ctx, &resp, hmOrderIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error {
|
||||
err := m.QueryRowCtx(ctx, &resp, tydataOrderIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error {
|
||||
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", orderRows, m.table)
|
||||
return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo)
|
||||
})
|
||||
@@ -115,9 +115,9 @@ func (m *defaultOrderModel) FindOne(ctx context.Context, id int64) (*Order, erro
|
||||
}
|
||||
|
||||
func (m *defaultOrderModel) FindOneByOrderNo(ctx context.Context, orderNo string) (*Order, error) {
|
||||
hmOrderOrderNoKey := fmt.Sprintf("%s%v", cacheHmOrderOrderNoPrefix, orderNo)
|
||||
tydataOrderOrderNoKey := fmt.Sprintf("%s%v", cacheTydataOrderOrderNoPrefix, orderNo)
|
||||
var resp Order
|
||||
err := m.QueryRowIndexCtx(ctx, &resp, hmOrderOrderNoKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
||||
err := m.QueryRowIndexCtx(ctx, &resp, tydataOrderOrderNoKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
||||
query := fmt.Sprintf("select %s from %s where `order_no` = ? and del_state = ? limit 1", orderRows, m.table)
|
||||
if err := conn.QueryRowCtx(ctx, &resp, query, orderNo, globalkey.DelStateNo); err != nil {
|
||||
return nil, err
|
||||
@@ -139,15 +139,15 @@ func (m *defaultOrderModel) Update(ctx context.Context, session sqlx.Session, ne
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hmOrderIdKey := fmt.Sprintf("%s%v", cacheHmOrderIdPrefix, data.Id)
|
||||
hmOrderOrderNoKey := fmt.Sprintf("%s%v", cacheHmOrderOrderNoPrefix, data.OrderNo)
|
||||
tydataOrderIdKey := fmt.Sprintf("%s%v", cacheTydataOrderIdPrefix, data.Id)
|
||||
tydataOrderOrderNoKey := fmt.Sprintf("%s%v", cacheTydataOrderOrderNoPrefix, data.OrderNo)
|
||||
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, orderRowsWithPlaceHolder)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.Id)
|
||||
return session.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.SalesCost, newData.Id)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.Id)
|
||||
}, hmOrderIdKey, hmOrderOrderNoKey)
|
||||
return conn.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.SalesCost, newData.Id)
|
||||
}, tydataOrderIdKey, tydataOrderOrderNoKey)
|
||||
}
|
||||
|
||||
func (m *defaultOrderModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *Order) error {
|
||||
@@ -162,15 +162,15 @@ func (m *defaultOrderModel) UpdateWithVersion(ctx context.Context, session sqlx.
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hmOrderIdKey := fmt.Sprintf("%s%v", cacheHmOrderIdPrefix, data.Id)
|
||||
hmOrderOrderNoKey := fmt.Sprintf("%s%v", cacheHmOrderOrderNoPrefix, data.OrderNo)
|
||||
tydataOrderIdKey := fmt.Sprintf("%s%v", cacheTydataOrderIdPrefix, data.Id)
|
||||
tydataOrderOrderNoKey := fmt.Sprintf("%s%v", cacheTydataOrderOrderNoPrefix, data.OrderNo)
|
||||
sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, orderRowsWithPlaceHolder)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.Id, oldVersion)
|
||||
return session.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.SalesCost, newData.Id, oldVersion)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.Id, oldVersion)
|
||||
}, hmOrderIdKey, hmOrderOrderNoKey)
|
||||
return conn.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.SalesCost, newData.Id, oldVersion)
|
||||
}, tydataOrderIdKey, tydataOrderOrderNoKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -393,19 +393,19 @@ func (m *defaultOrderModel) Delete(ctx context.Context, session sqlx.Session, id
|
||||
return err
|
||||
}
|
||||
|
||||
hmOrderIdKey := fmt.Sprintf("%s%v", cacheHmOrderIdPrefix, id)
|
||||
hmOrderOrderNoKey := fmt.Sprintf("%s%v", cacheHmOrderOrderNoPrefix, data.OrderNo)
|
||||
tydataOrderIdKey := fmt.Sprintf("%s%v", cacheTydataOrderIdPrefix, id)
|
||||
tydataOrderOrderNoKey := fmt.Sprintf("%s%v", cacheTydataOrderOrderNoPrefix, data.OrderNo)
|
||||
_, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, id)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, id)
|
||||
}, hmOrderIdKey, hmOrderOrderNoKey)
|
||||
}, tydataOrderIdKey, tydataOrderOrderNoKey)
|
||||
return err
|
||||
}
|
||||
func (m *defaultOrderModel) formatPrimary(primary interface{}) string {
|
||||
return fmt.Sprintf("%s%v", cacheHmOrderIdPrefix, primary)
|
||||
return fmt.Sprintf("%s%v", cacheTydataOrderIdPrefix, primary)
|
||||
}
|
||||
func (m *defaultOrderModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error {
|
||||
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", orderRows, m.table)
|
||||
|
||||
@@ -2,9 +2,9 @@ package model
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tydata-server/common/globalkey"
|
||||
"fmt"
|
||||
"time"
|
||||
"tydata-server/common/globalkey"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/stores/cache"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
|
||||
76
app/main/model/queryUserRecordModel.go
Normal file
76
app/main/model/queryUserRecordModel.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"tydata-server/common/globalkey"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/stores/cache"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlc"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
)
|
||||
|
||||
var _ QueryUserRecordModel = (*customQueryUserRecordModel)(nil)
|
||||
|
||||
type (
|
||||
// QueryUserRecordModel is an interface to be customized, add more methods here,
|
||||
// and implement the added methods in customQueryUserRecordModel.
|
||||
QueryUserRecordModel interface {
|
||||
queryUserRecordModel
|
||||
FindOneByQueryNo(ctx context.Context, queryNo string) (*QueryUserRecord, error)
|
||||
CountByEncryptedIdCardIn72Hours(ctx context.Context, encryptedIdCard string) (int64, error)
|
||||
}
|
||||
|
||||
customQueryUserRecordModel struct {
|
||||
*defaultQueryUserRecordModel
|
||||
}
|
||||
)
|
||||
|
||||
// FindOneByQueryNo 根据 query_no 查询一条记录(query_no 与 order.order_no 一致)
|
||||
func (m *customQueryUserRecordModel) FindOneByQueryNo(ctx context.Context, queryNo string) (*QueryUserRecord, error) {
|
||||
query := fmt.Sprintf("select %s from %s where `query_no` = ? and del_state = ? limit 1", queryUserRecordRows, m.table)
|
||||
var resp QueryUserRecord
|
||||
err := m.QueryRowNoCacheCtx(ctx, &resp, query, queryNo, globalkey.DelStateNo)
|
||||
switch err {
|
||||
case nil:
|
||||
return &resp, nil
|
||||
case sqlc.ErrNotFound:
|
||||
return nil, ErrNotFound
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// CountByEncryptedIdCardIn72Hours 查询72小时内某个加密身份证号的已支付查询次数
|
||||
func (m *customQueryUserRecordModel) CountByEncryptedIdCardIn72Hours(ctx context.Context, encryptedIdCard string) (int64, error) {
|
||||
// 计算72小时前的时间
|
||||
seventyTwoHoursAgo := time.Now().Add(-72 * time.Hour)
|
||||
|
||||
// 关联 order 表,只统计已支付的订单
|
||||
query := fmt.Sprintf(`
|
||||
select count(*)
|
||||
from %s qur
|
||||
inner join `+"`order`"+` o on qur.order_id = o.id
|
||||
where qur.id_card = ?
|
||||
and qur.create_time >= ?
|
||||
and qur.del_state = ?
|
||||
and qur.order_id > 0
|
||||
and o.status = 'paid'
|
||||
and o.del_state = ?
|
||||
`, m.table)
|
||||
var count int64
|
||||
err := m.QueryRowNoCacheCtx(ctx, &count, query, encryptedIdCard, seventyTwoHoursAgo, globalkey.DelStateNo, globalkey.DelStateNo)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// NewQueryUserRecordModel returns a model for the database table.
|
||||
func NewQueryUserRecordModel(conn sqlx.SqlConn, c cache.CacheConf) QueryUserRecordModel {
|
||||
return &customQueryUserRecordModel{
|
||||
defaultQueryUserRecordModel: newQueryUserRecordModel(conn, c),
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user