diff --git a/services/gateway-service/internal/transport/http/httproutes/router.go b/services/gateway-service/internal/transport/http/httproutes/router.go index e6efa71b..4a938c0a 100644 --- a/services/gateway-service/internal/transport/http/httproutes/router.go +++ b/services/gateway-service/internal/transport/http/httproutes/router.go @@ -75,6 +75,7 @@ type UserHandlers struct { GetHostCenterAgency http.HandlerFunc GetHostCenterPlatformPolicy http.HandlerFunc GetAgencyCenterOverview http.HandlerFunc + GetAgencyCenterPlatformPolicy http.HandlerFunc ListAgencyCenterHosts http.HandlerFunc ListAgencyCenterApplications http.HandlerFunc ReviewAgencyCenterApplication http.HandlerFunc @@ -318,6 +319,7 @@ func (r routes) registerUserRoutes() { r.profile("/host-center/agency", http.MethodGet, h.GetHostCenterAgency) r.profile("/host-center/platform-policy", http.MethodGet, h.GetHostCenterPlatformPolicy) r.profile("/agency-center/overview", http.MethodGet, h.GetAgencyCenterOverview) + r.profile("/agency-center/platform-policy", http.MethodGet, h.GetAgencyCenterPlatformPolicy) r.profile("/agency-center/hosts", http.MethodGet, h.ListAgencyCenterHosts) r.profile("/agency-center/applications", http.MethodGet, h.ListAgencyCenterApplications) r.profile("/agency-center/applications/{application_id}/review", http.MethodPost, h.ReviewAgencyCenterApplication) diff --git a/services/gateway-service/internal/transport/http/response_test.go b/services/gateway-service/internal/transport/http/response_test.go index e0cb5a10..58d0f2a0 100644 --- a/services/gateway-service/internal/transport/http/response_test.go +++ b/services/gateway-service/internal/transport/http/response_test.go @@ -3634,6 +3634,72 @@ func TestAgencyCenterOverviewUsesOwnerAgencySalaryAndPendingApplications(t *test } } +func TestAgencyCenterPlatformPolicyUsesAgencyRegion(t *testing.T) { + hostClient := &fakeUserHostClient{ + roleSummary: &userv1.UserRoleSummary{UserId: 42, IsManager: true, AgencyId: 7001}, + getAgencyResp: &userv1.GetAgencyResponse{Agency: &userv1.Agency{ + AgencyId: 7001, + OwnerUserId: 42, + RegionId: 31, + Name: "Yumi Star Agency", + Status: "active", + }}, + } + walletClient := &fakeWalletClient{ + hostSalaryPolicyResp: &walletv1.GetActiveHostSalaryPolicyResponse{ + Found: true, + Policy: &walletv1.HostSalaryPolicy{ + PolicyId: 9101, + Name: "Agency Region Policy", + RegionId: 31, + Status: "active", + SettlementMode: "half_month", + SettlementTriggerMode: "manual", + GiftCoinToDiamondRatio: "1.0000", + ResidualDiamondToUsdRate: "0.0100", + Levels: []*walletv1.HostSalaryPolicyLevel{ + {LevelNo: 1, RequiredDiamonds: 1000, HostSalaryUsdMinor: 1200, HostCoinReward: 100, AgencySalaryUsdMinor: 240, Status: "active", SortOrder: 1}, + {LevelNo: 2, RequiredDiamonds: 3000, HostSalaryUsdMinor: 3600, HostCoinReward: 300, AgencySalaryUsdMinor: 720, Status: "active", SortOrder: 2}, + }, + }, + }, + } + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, &fakeUserProfileClient{}) + handler.SetUserHostClient(hostClient) + handler.SetWalletClient(walletClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodGet, "/api/v1/agency-center/platform-policy", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42)) + request.Header.Set("X-Request-ID", "req-agency-policy") + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if hostClient.lastRoleSummary == nil || hostClient.lastRoleSummary.GetUserId() != 42 || hostClient.lastGetAgency == nil || hostClient.lastGetAgency.GetAgencyId() != 7001 { + t.Fatalf("agency owner resolution mismatch: role=%+v agency=%+v", hostClient.lastRoleSummary, hostClient.lastGetAgency) + } + if walletClient.lastHostSalaryPolicy == nil || walletClient.lastHostSalaryPolicy.GetRegionId() != 31 || walletClient.lastHostSalaryPolicy.GetSettlementTriggerMode() != "" || walletClient.lastHostSalaryPolicy.GetAppCode() == "" || walletClient.lastHostSalaryPolicy.GetRequestId() == "" { + t.Fatalf("agency policy request mismatch: %+v", walletClient.lastHostSalaryPolicy) + } + if walletClient.lastHostSalaryProgress != nil { + t.Fatalf("agency policy should not request host progress: %+v", walletClient.lastHostSalaryProgress) + } + var response httpkit.ResponseEnvelope + if err := json.NewDecoder(recorder.Body).Decode(&response); err != nil { + t.Fatalf("decode response failed: %v", err) + } + data := response.Data.(map[string]any) + policy := data["policy"].(map[string]any) + levels := policy["levels"].([]any) + secondLevel := levels[1].(map[string]any) + if data["found"] != true || data["agency_region_id"] != float64(31) || policy["policy_id"] != "9101" || len(levels) != 2 || secondLevel["agency_salary_usd"] != 7.2 { + t.Fatalf("agency policy response mismatch: %+v", data) + } +} + func TestBDCenterOverviewUsesBDSalaryAndDirectAgencies(t *testing.T) { hostClient := &fakeUserHostClient{ bdProfile: &userv1.BDProfile{UserId: 42, Role: "bd", Status: "active", RegionId: 1001}, diff --git a/services/gateway-service/internal/transport/http/userapi/agency_center_handler.go b/services/gateway-service/internal/transport/http/userapi/agency_center_handler.go index 4789056e..2273bc34 100644 --- a/services/gateway-service/internal/transport/http/userapi/agency_center_handler.go +++ b/services/gateway-service/internal/transport/http/userapi/agency_center_handler.go @@ -109,6 +109,36 @@ func (h *Handler) getAgencyCenterOverview(writer http.ResponseWriter, request *h }) } +func (h *Handler) getAgencyCenterPlatformPolicy(writer http.ResponseWriter, request *http.Request) { + agency, ok := h.resolveCurrentOwnerAgency(writer, request) + if !ok { + return + } + if h.walletClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + + // Agency Center 不是主播身份,不能复用 host-center 的 active host 校验;这里固定用当前 agency 的区域读取完整工资政策。 + resp, err := h.walletClient.GetActiveHostSalaryPolicy(request.Context(), &walletv1.GetActiveHostSalaryPolicyRequest{ + RequestId: httpkit.RequestIDFromContext(request.Context()), + AppCode: appcode.FromContext(request.Context()), + RegionId: agency.GetRegionId(), + SettlementTriggerMode: "", + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + + // H5 需要完整政策明细;hostCenterPolicyFromProto 会保留政策元数据和所有等级行,agency 端不计算主播等级进度。 + httpkit.WriteOK(writer, request, map[string]any{ + "found": resp.GetFound(), + "agency_region_id": agency.GetRegionId(), + "policy": hostCenterPolicyFromProto(resp.GetPolicy()), + }) +} + func (h *Handler) listAgencyCenterHosts(writer http.ResponseWriter, request *http.Request) { agency, ok := h.resolveCurrentOwnerAgency(writer, request) if !ok { diff --git a/services/gateway-service/internal/transport/http/userapi/handler.go b/services/gateway-service/internal/transport/http/userapi/handler.go index b97dd841..3ab9ab2e 100644 --- a/services/gateway-service/internal/transport/http/userapi/handler.go +++ b/services/gateway-service/internal/transport/http/userapi/handler.go @@ -59,6 +59,7 @@ func (h *Handler) UserHandlers() httproutes.UserHandlers { GetHostCenterAgency: h.getHostCenterAgency, GetHostCenterPlatformPolicy: h.getHostCenterPlatformPolicy, GetAgencyCenterOverview: h.getAgencyCenterOverview, + GetAgencyCenterPlatformPolicy: h.getAgencyCenterPlatformPolicy, ListAgencyCenterHosts: h.listAgencyCenterHosts, ListAgencyCenterApplications: h.listAgencyCenterApplications, ReviewAgencyCenterApplication: h.reviewAgencyCenterApplication,