650 lines
23 KiB
Go
650 lines
23 KiB
Go
package hostorg
|
||
|
||
import (
|
||
"database/sql"
|
||
"fmt"
|
||
"strconv"
|
||
"strings"
|
||
|
||
"hyapp-admin-server/internal/integration/userclient"
|
||
"hyapp-admin-server/internal/integration/walletclient"
|
||
"hyapp-admin-server/internal/middleware"
|
||
"hyapp-admin-server/internal/modules/shared"
|
||
"hyapp-admin-server/internal/response"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
type Handler struct {
|
||
service *Service
|
||
audit shared.OperationLogger
|
||
}
|
||
|
||
func New(userClient userclient.Client, walletClient walletclient.Client, userDB *sql.DB, walletDB *sql.DB, adminDB *sql.DB, audit shared.OperationLogger) *Handler {
|
||
return &Handler{service: NewService(userClient, walletClient, NewReader(userDB, walletDB, adminDB)), audit: audit}
|
||
}
|
||
|
||
func (h *Handler) ListBDLeaders(c *gin.Context) {
|
||
query, ok := parseListQuery(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
items, total, err := h.service.ListBDLeaders(c.Request.Context(), query)
|
||
if err != nil {
|
||
response.ServerError(c, "获取 BD Leader 列表失败")
|
||
return
|
||
}
|
||
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
|
||
}
|
||
|
||
func (h *Handler) ListBDs(c *gin.Context) {
|
||
query, ok := parseListQuery(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
items, total, err := h.service.ListBDs(c.Request.Context(), query)
|
||
if err != nil {
|
||
response.ServerError(c, "获取 BD 列表失败")
|
||
return
|
||
}
|
||
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
|
||
}
|
||
|
||
func (h *Handler) ListAgencies(c *gin.Context) {
|
||
query, ok := parseListQuery(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
items, total, err := h.service.ListAgencies(c.Request.Context(), query)
|
||
if err != nil {
|
||
response.ServerError(c, "获取 Agency 列表失败")
|
||
return
|
||
}
|
||
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
|
||
}
|
||
|
||
func (h *Handler) ListManagers(c *gin.Context) {
|
||
query, ok := parseListQuery(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
items, total, err := h.service.ListManagers(c.Request.Context(), query)
|
||
if err != nil {
|
||
response.ServerError(c, "获取经理列表失败")
|
||
return
|
||
}
|
||
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
|
||
}
|
||
|
||
func (h *Handler) CreateManager(c *gin.Context) {
|
||
var req createManagerRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "经理参数不正确")
|
||
return
|
||
}
|
||
item, err := h.service.CreateManager(c.Request.Context(), adminActorID(c), middleware.CurrentRequestID(c), req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "create-manager", "manager_profiles", item.UserID,
|
||
fmt.Sprintf("user_id=%d contact=%q", item.UserID, strings.TrimSpace(req.Contact)))
|
||
response.Created(c, item)
|
||
}
|
||
|
||
func (h *Handler) UpdateManager(c *gin.Context) {
|
||
userID, ok := parseInt64ID(c, "user_id")
|
||
if !ok {
|
||
return
|
||
}
|
||
var req updateManagerRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "经理参数不正确")
|
||
return
|
||
}
|
||
item, err := h.service.UpdateManager(c.Request.Context(), adminActorID(c), userID, req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
statusDetail := ""
|
||
if req.Status != nil && strings.TrimSpace(*req.Status) != "" {
|
||
statusDetail = " status=" + strings.ToLower(strings.TrimSpace(*req.Status))
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "update-manager", "manager_profiles", item.UserID,
|
||
fmt.Sprintf("user_id=%d permissions_updated=true%s", item.UserID, statusDetail))
|
||
response.OK(c, item)
|
||
}
|
||
|
||
func (h *Handler) ListHosts(c *gin.Context) {
|
||
query, ok := parseListQuery(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
items, total, err := h.service.ListHosts(c.Request.Context(), query)
|
||
if err != nil {
|
||
response.ServerError(c, "获取主播列表失败")
|
||
return
|
||
}
|
||
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
|
||
}
|
||
|
||
func (h *Handler) ListCoinSellers(c *gin.Context) {
|
||
query, ok := parseListQuery(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
items, total, err := h.service.ListCoinSellers(c.Request.Context(), query)
|
||
if err != nil {
|
||
response.ServerError(c, "获取币商列表失败")
|
||
return
|
||
}
|
||
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
|
||
}
|
||
|
||
func (h *Handler) ListCoinSellerSubApplications(c *gin.Context) {
|
||
query, ok := parseListQuery(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
items, total, err := h.service.ListCoinSellerSubApplications(c.Request.Context(), query)
|
||
if err != nil {
|
||
response.ServerError(c, "获取子币商申请列表失败")
|
||
return
|
||
}
|
||
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
|
||
}
|
||
|
||
func (h *Handler) ListCoinSellerSubSellers(c *gin.Context) {
|
||
parentUserID, ok := parseInt64ID(c, "user_id")
|
||
if !ok {
|
||
return
|
||
}
|
||
query, ok := parseListQuery(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
items, total, err := h.service.ListCoinSellerSubSellers(c.Request.Context(), parentUserID, query)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
|
||
}
|
||
|
||
func (h *Handler) ApproveCoinSellerSubApplication(c *gin.Context) {
|
||
h.reviewCoinSellerSubApplication(c, "approved")
|
||
}
|
||
|
||
func (h *Handler) RejectCoinSellerSubApplication(c *gin.Context) {
|
||
h.reviewCoinSellerSubApplication(c, "rejected")
|
||
}
|
||
|
||
func (h *Handler) reviewCoinSellerSubApplication(c *gin.Context, decision string) {
|
||
applicationID, ok := parseInt64ID(c, "application_id")
|
||
if !ok {
|
||
return
|
||
}
|
||
var req coinSellerSubApplicationReviewRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "子币商申请审核参数不正确")
|
||
return
|
||
}
|
||
result, err := h.service.ReviewCoinSellerSubApplication(c.Request.Context(), adminActorID(c), applicationID, middleware.CurrentRequestID(c), decision, req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "review-coin-seller-sub-application", "coin_seller_sub_applications", applicationID,
|
||
fmt.Sprintf("command_id=%s application_id=%d decision=%s reason=%q", strings.TrimSpace(req.CommandID), applicationID, decision, strings.TrimSpace(req.Reason)))
|
||
response.OK(c, result)
|
||
}
|
||
|
||
func (h *Handler) ListSalaryWalletHistory(c *gin.Context) {
|
||
query, ok := parseSalaryWalletHistoryQuery(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
items, total, err := h.service.ListSalaryWalletHistory(c.Request.Context(), query)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
|
||
}
|
||
|
||
func (h *Handler) AdjustSalaryWallet(c *gin.Context) {
|
||
var req salaryWalletAdjustRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "工资钱包操作参数不正确")
|
||
return
|
||
}
|
||
result, err := h.service.AdjustSalaryWallet(c.Request.Context(), adminActorID(c), middleware.CurrentRequestID(c), req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "salary-wallet-adjust", "wallet_entries", req.TargetUserID.Int64(),
|
||
fmt.Sprintf("role=%s target_user_id=%d amount_minor=%d transaction_id=%s reason=%q",
|
||
result.Role, req.TargetUserID.Int64(), result.AmountMinor, result.TransactionID, strings.TrimSpace(req.Reason)))
|
||
response.Created(c, result)
|
||
}
|
||
|
||
func (h *Handler) CreateBDLeader(c *gin.Context) {
|
||
var req createBDLeaderRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "BD Leader 参数不正确")
|
||
return
|
||
}
|
||
profile, err := h.service.CreateBDLeader(c.Request.Context(), adminActorID(c), middleware.CurrentRequestID(c), req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "create-bd-leader", "bd_leader_profiles", profile.UserID,
|
||
fmt.Sprintf("command_id=%s user_id=%d region_id=%d position_alias=%q reason=%q", strings.TrimSpace(req.CommandID), profile.UserID, profile.RegionID, strings.TrimSpace(req.PositionAlias), strings.TrimSpace(req.Reason)))
|
||
response.Created(c, profile)
|
||
}
|
||
|
||
func (h *Handler) CreateBD(c *gin.Context) {
|
||
var req createBDRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "BD 参数不正确")
|
||
return
|
||
}
|
||
profile, err := h.service.CreateBD(c.Request.Context(), adminActorID(c), middleware.CurrentRequestID(c), req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "create-bd", "bd_profiles", profile.UserID,
|
||
fmt.Sprintf("command_id=%s user_id=%d parent_leader_user_id=%d reason=%q", strings.TrimSpace(req.CommandID), profile.UserID, profile.ParentLeaderUserID, strings.TrimSpace(req.Reason)))
|
||
response.Created(c, profile)
|
||
}
|
||
|
||
func (h *Handler) SetBDStatus(c *gin.Context) {
|
||
targetUserID, ok := parseInt64ID(c, "user_id")
|
||
if !ok {
|
||
return
|
||
}
|
||
var req bdStatusRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "BD 状态参数不正确")
|
||
return
|
||
}
|
||
role, auditTarget := bdRoleFromStatusRoute(c)
|
||
profile, err := h.service.SetBDStatus(c.Request.Context(), adminActorID(c), targetUserID, middleware.CurrentRequestID(c), role, req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "set-bd-status", auditTarget, profile.UserID,
|
||
fmt.Sprintf("command_id=%s user_id=%d status=%s reason=%q", strings.TrimSpace(req.CommandID), profile.UserID, profile.Status, strings.TrimSpace(req.Reason)))
|
||
response.OK(c, profile)
|
||
}
|
||
|
||
func bdRoleFromStatusRoute(c *gin.Context) (string, string) {
|
||
return bdRoleFromStatusPath(c.FullPath())
|
||
}
|
||
|
||
func bdRoleFromStatusPath(fullPath string) (string, string) {
|
||
// FullPath 带有外层 /api/v1 分组;只要命中 BD Leader 状态路由片段,就必须走独立的 bd_leader_profiles,避免误查普通 bd_profiles。
|
||
if strings.Contains(fullPath, "/admin/bd-leaders/") {
|
||
return "bd_leader", "bd_leader_profiles"
|
||
}
|
||
return "bd", "bd_profiles"
|
||
}
|
||
|
||
func (h *Handler) UpdateBDLeaderPositionAlias(c *gin.Context) {
|
||
targetUserID, ok := parseInt64ID(c, "user_id")
|
||
if !ok {
|
||
return
|
||
}
|
||
var req bdLeaderPositionAliasRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "职位别名参数不正确")
|
||
return
|
||
}
|
||
profile, err := h.service.UpdateBDLeaderPositionAlias(c.Request.Context(), adminActorID(c), targetUserID, req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "set-bd-leader-position-alias", "admin_bd_leader_position_aliases", profile.UserID,
|
||
fmt.Sprintf("command_id=%s user_id=%d position_alias=%q reason=%q", strings.TrimSpace(req.CommandID), profile.UserID, profile.PositionAlias, strings.TrimSpace(req.Reason)))
|
||
response.OK(c, profile)
|
||
}
|
||
|
||
func (h *Handler) DeleteBDLeader(c *gin.Context) {
|
||
targetUserID, ok := parseInt64ID(c, "user_id")
|
||
if !ok {
|
||
return
|
||
}
|
||
profile, err := h.service.DeleteBDLeader(c.Request.Context(), targetUserID)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "delete-bd-leader", "bd_leader_profiles", profile.UserID,
|
||
fmt.Sprintf("user_id=%d", profile.UserID))
|
||
response.OK(c, profile)
|
||
}
|
||
|
||
func (h *Handler) CreateCoinSeller(c *gin.Context) {
|
||
var req createCoinSellerRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "币商参数不正确")
|
||
return
|
||
}
|
||
profile, err := h.service.CreateCoinSeller(c.Request.Context(), adminActorID(c), middleware.CurrentRequestID(c), req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "create-coin-seller", "coin_seller_profiles", profile.UserID,
|
||
fmt.Sprintf("command_id=%s user_id=%d reason=%q", strings.TrimSpace(req.CommandID), profile.UserID, strings.TrimSpace(req.Reason)))
|
||
response.Created(c, profile)
|
||
}
|
||
|
||
func (h *Handler) SetCoinSellerStatus(c *gin.Context) {
|
||
targetUserID, ok := parseInt64ID(c, "user_id")
|
||
if !ok {
|
||
return
|
||
}
|
||
var req coinSellerStatusRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "币商状态参数不正确")
|
||
return
|
||
}
|
||
profile, err := h.service.SetCoinSellerStatus(c.Request.Context(), adminActorID(c), targetUserID, middleware.CurrentRequestID(c), req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "set-coin-seller-status", "coin_seller_profiles", profile.UserID,
|
||
fmt.Sprintf("command_id=%s user_id=%d status=%s reason=%q", strings.TrimSpace(req.CommandID), profile.UserID, profile.Status, strings.TrimSpace(req.Reason)))
|
||
response.OK(c, profile)
|
||
}
|
||
|
||
func (h *Handler) CreditCoinSellerStock(c *gin.Context) {
|
||
sellerUserID, ok := parseInt64ID(c, "user_id")
|
||
if !ok {
|
||
return
|
||
}
|
||
var req coinSellerStockCreditRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "币商进货参数不正确")
|
||
return
|
||
}
|
||
result, err := h.service.CreditCoinSellerStock(c.Request.Context(), adminActorID(c), sellerUserID, middleware.CurrentRequestID(c), req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "coin-seller-stock-credit", "coin_seller_stock_records", sellerUserID,
|
||
fmt.Sprintf("command_id=%s seller_user_id=%d stock_type=%s coin_amount=%d paid_currency_code=%s paid_amount_micro=%d transaction_id=%s reason=%q",
|
||
strings.TrimSpace(req.CommandID), sellerUserID, result.GetStockType(), result.GetCoinAmount(), result.GetPaidCurrencyCode(), result.GetPaidAmountMicro(), result.GetTransactionId(), strings.TrimSpace(req.Reason)))
|
||
response.Created(c, coinSellerStockCreditFromProto(result))
|
||
}
|
||
|
||
func (h *Handler) DebitCoinSellerStock(c *gin.Context) {
|
||
sellerUserID, ok := parseInt64ID(c, "user_id")
|
||
if !ok {
|
||
return
|
||
}
|
||
var req coinSellerStockDebitRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "币商扣除参数不正确")
|
||
return
|
||
}
|
||
result, err := h.service.DebitCoinSellerStock(c.Request.Context(), adminActorID(c), sellerUserID, middleware.CurrentRequestID(c), req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "coin-seller-stock-debit", "coin_seller_stock_records", sellerUserID,
|
||
fmt.Sprintf("command_id=%s seller_user_id=%d stock_type=%s coin_amount=%d paid_currency_code=%s paid_amount_micro=%d transaction_id=%s reason=%q",
|
||
strings.TrimSpace(req.CommandID), sellerUserID, result.GetStockType(), result.GetCoinAmount(), result.GetPaidCurrencyCode(), result.GetPaidAmountMicro(), result.GetTransactionId(), strings.TrimSpace(req.Reason)))
|
||
response.Created(c, coinSellerStockDebitFromProto(sellerUserID, req.CoinAmount, result))
|
||
}
|
||
|
||
func (h *Handler) GetCoinSellerSalaryRates(c *gin.Context) {
|
||
regionID, ok := parseInt64ID(c, "region_id")
|
||
if !ok {
|
||
return
|
||
}
|
||
items, err := h.service.GetCoinSellerSalaryRates(c.Request.Context(), regionID)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.OK(c, gin.H{"regionId": regionID, "tiers": items})
|
||
}
|
||
|
||
func (h *Handler) ReplaceCoinSellerSalaryRates(c *gin.Context) {
|
||
regionID, ok := parseInt64ID(c, "region_id")
|
||
if !ok {
|
||
return
|
||
}
|
||
var req replaceCoinSellerSalaryRatesRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "币商工资兑换比例参数不正确")
|
||
return
|
||
}
|
||
items, err := h.service.ReplaceCoinSellerSalaryRates(c.Request.Context(), adminActorID(c), regionID, req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "coin-seller-salary-rates", "coin_seller_salary_exchange_rate_tiers", regionID,
|
||
fmt.Sprintf("region_id=%d tiers=%d", regionID, len(items)))
|
||
response.OK(c, gin.H{"regionId": regionID, "tiers": items})
|
||
}
|
||
|
||
func (h *Handler) CreateAgency(c *gin.Context) {
|
||
var req createAgencyRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "Agency 参数不正确")
|
||
return
|
||
}
|
||
result, err := h.service.CreateAgency(c.Request.Context(), adminActorID(c), middleware.CurrentRequestID(c), req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "create-agency", "agencies", result.Agency.AgencyID,
|
||
fmt.Sprintf("command_id=%s agency_id=%d owner_user_id=%d parent_bd_user_id=%d join_enabled=%t reason=%q",
|
||
strings.TrimSpace(req.CommandID), result.Agency.AgencyID, result.Agency.OwnerUserID, result.Agency.ParentBDUserID, result.Agency.JoinEnabled, strings.TrimSpace(req.Reason)))
|
||
response.Created(c, result)
|
||
}
|
||
|
||
func (h *Handler) AdminAddAgencyHost(c *gin.Context) {
|
||
agencyID, ok := parseInt64ID(c, "agency_id")
|
||
if !ok {
|
||
return
|
||
}
|
||
var req agencyHostAddRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "添加 Host 参数不正确")
|
||
return
|
||
}
|
||
result, err := h.service.AdminAddAgencyHost(c.Request.Context(), adminActorID(c), agencyID, middleware.CurrentRequestID(c), req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "add-agency-host", "agency_memberships", result.Membership.MembershipID,
|
||
fmt.Sprintf("command_id=%s agency_id=%d host_user_id=%d reason=%q",
|
||
strings.TrimSpace(req.CommandID), agencyID, result.Membership.HostUserID, strings.TrimSpace(req.Reason)))
|
||
response.Created(c, result)
|
||
}
|
||
|
||
func (h *Handler) CloseAgency(c *gin.Context) {
|
||
agencyID, ok := parseInt64ID(c, "agency_id")
|
||
if !ok {
|
||
return
|
||
}
|
||
var req agencyCloseRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "关闭 Agency 参数不正确")
|
||
return
|
||
}
|
||
agency, err := h.service.CloseAgency(c.Request.Context(), adminActorID(c), agencyID, middleware.CurrentRequestID(c), req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "close-agency", "agencies", agency.AgencyID,
|
||
fmt.Sprintf("command_id=%s agency_id=%d status=%s reason=%q", strings.TrimSpace(req.CommandID), agency.AgencyID, agency.Status, strings.TrimSpace(req.Reason)))
|
||
response.OK(c, agency)
|
||
}
|
||
|
||
func (h *Handler) SetAgencyStatus(c *gin.Context) {
|
||
agencyID, ok := parseInt64ID(c, "agency_id")
|
||
if !ok {
|
||
return
|
||
}
|
||
var req agencyStatusRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "Agency 状态参数不正确")
|
||
return
|
||
}
|
||
agency, err := h.service.SetAgencyStatus(c.Request.Context(), adminActorID(c), agencyID, middleware.CurrentRequestID(c), req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "set-agency-status", "agencies", agency.AgencyID,
|
||
fmt.Sprintf("command_id=%s agency_id=%d status=%s reason=%q", strings.TrimSpace(req.CommandID), agency.AgencyID, agency.Status, strings.TrimSpace(req.Reason)))
|
||
response.OK(c, agency)
|
||
}
|
||
|
||
func (h *Handler) DeleteAgency(c *gin.Context) {
|
||
agencyID, ok := parseInt64ID(c, "agency_id")
|
||
if !ok {
|
||
return
|
||
}
|
||
var req agencyDeleteRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "删除 Agency 参数不正确")
|
||
return
|
||
}
|
||
agency, err := h.service.DeleteAgency(c.Request.Context(), adminActorID(c), agencyID, middleware.CurrentRequestID(c), req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "delete-agency", "agencies", agency.AgencyID,
|
||
fmt.Sprintf("command_id=%s agency_id=%d status=%s reason=%q", strings.TrimSpace(req.CommandID), agency.AgencyID, agency.Status, strings.TrimSpace(req.Reason)))
|
||
response.OK(c, agency)
|
||
}
|
||
|
||
func (h *Handler) SetAgencyJoinEnabled(c *gin.Context) {
|
||
agencyID, ok := parseInt64ID(c, "agency_id")
|
||
if !ok {
|
||
return
|
||
}
|
||
var req agencyJoinEnabledRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "Agency 入会开关参数不正确")
|
||
return
|
||
}
|
||
agency, err := h.service.SetAgencyJoinEnabled(c.Request.Context(), adminActorID(c), agencyID, middleware.CurrentRequestID(c), req)
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
writeHostOrgAuditLog(c, h.audit, "set-agency-join-enabled", "agencies", agency.AgencyID,
|
||
fmt.Sprintf("command_id=%s agency_id=%d join_enabled=%t reason=%q", strings.TrimSpace(req.CommandID), agency.AgencyID, agency.JoinEnabled, strings.TrimSpace(req.Reason)))
|
||
response.OK(c, agency)
|
||
}
|
||
|
||
func adminActorID(c *gin.Context) int64 {
|
||
return int64(shared.ActorFromContext(c).UserID)
|
||
}
|
||
|
||
func parseInt64ID(c *gin.Context, name string) (int64, bool) {
|
||
id, ok := shared.ParseID(c, name)
|
||
if !ok {
|
||
return 0, false
|
||
}
|
||
return int64(id), true
|
||
}
|
||
|
||
func parseListQuery(c *gin.Context) (listQuery, bool) {
|
||
options := shared.ListOptions(c)
|
||
query := listQuery{
|
||
Page: options.Page,
|
||
PageSize: options.PageSize,
|
||
Keyword: options.Keyword,
|
||
UserFilter: shared.UserIdentityFilterFromQuery(c, ""),
|
||
OwnerFilter: shared.UserIdentityFilterFromQuery(c, "owner"),
|
||
ParentLeaderFilter: shared.UserIdentityFilterFromQuery(c, "parent_leader"),
|
||
ParentBDFilter: shared.UserIdentityFilterFromQuery(c, "parent_bd"),
|
||
Status: options.Status,
|
||
SortBy: firstNonBlank(c.Query("sortBy"), c.Query("sort_by")),
|
||
SortDirection: firstNonBlank(c.Query("sortDirection"), c.Query("sort_direction"), c.Query("order")),
|
||
}
|
||
var ok bool
|
||
if query.RegionID, ok = parseOptionalInt64Query(c, "regionId", "region_id"); !ok {
|
||
return listQuery{}, false
|
||
}
|
||
if query.AgencyID, ok = parseOptionalInt64Query(c, "agencyId", "agency_id"); !ok {
|
||
return listQuery{}, false
|
||
}
|
||
if query.ParentBDUserID, ok = parseOptionalInt64Query(c, "parentBdUserId", "parent_bd_user_id"); !ok {
|
||
return listQuery{}, false
|
||
}
|
||
if query.ParentLeaderUserID, ok = parseOptionalInt64Query(c, "parentLeaderUserId", "parent_leader_user_id"); !ok {
|
||
return listQuery{}, false
|
||
}
|
||
if query.ParentUserID, ok = parseOptionalInt64Query(c, "parentUserId", "parent_user_id"); !ok {
|
||
return listQuery{}, false
|
||
}
|
||
if query.TargetUserID, ok = parseOptionalInt64Query(c, "targetUserId", "target_user_id"); !ok {
|
||
return listQuery{}, false
|
||
}
|
||
return normalizeListQuery(query), true
|
||
}
|
||
|
||
func parseSalaryWalletHistoryQuery(c *gin.Context) (salaryWalletHistoryQuery, bool) {
|
||
options := shared.ListOptions(c)
|
||
userID, ok := parseOptionalInt64Query(c, "userId", "user_id")
|
||
if !ok {
|
||
return salaryWalletHistoryQuery{}, false
|
||
}
|
||
if userID <= 0 {
|
||
response.BadRequest(c, "user_id 参数不正确")
|
||
return salaryWalletHistoryQuery{}, false
|
||
}
|
||
query := salaryWalletHistoryQuery{
|
||
Page: options.Page,
|
||
PageSize: options.PageSize,
|
||
Role: c.Query("role"),
|
||
UserID: userID,
|
||
}
|
||
return normalizeSalaryWalletHistoryQuery(query), true
|
||
}
|
||
|
||
func parseOptionalInt64Query(c *gin.Context, primary string, fallback string) (int64, bool) {
|
||
raw := strings.TrimSpace(c.Query(primary))
|
||
if raw == "" {
|
||
raw = strings.TrimSpace(c.Query(fallback))
|
||
}
|
||
if raw == "" {
|
||
return 0, true
|
||
}
|
||
value, err := strconv.ParseInt(raw, 10, 64)
|
||
if err != nil || value < 0 {
|
||
response.BadRequest(c, primary+" 参数不正确")
|
||
return 0, false
|
||
}
|
||
return value, true
|
||
}
|
||
|
||
func writeHostOrgAuditLog(c *gin.Context, logger shared.OperationLogger, action string, resource string, resourceID int64, detail string) {
|
||
// HostOrg 的后台审计只能写 hyapp-admin-server 自己的 admin_operation_logs。
|
||
// user-service 只接收业务命令并维护关系事实,不能反向保存后台审计数据。
|
||
shared.OperationLogWithResourceID(c, logger, action, resource, fmt.Sprintf("%d", resourceID), "success", detail)
|
||
}
|