using System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Tiku.Api.Contracts; using Tiku.Api.OpenApi; using Tiku.Application.Auth; using Tiku.Application.PlatformAdmin; using Tiku.Application.Security; using Tiku.Domain.Platform; namespace Tiku.Api.Controllers; [ApiController] [Tags("平台端-平台管理")] [Authorize(Policy = BackendPermissions.PlatformDashboardView)] [Produces("application/json")] [Route("api/platform")] public sealed class TenantProvisioningAdministrationController( ITenantProvisioningAdministrationService service, IPlatformApprovalService approvalService, PlatformAdminActorResolver actorResolver) : ControllerBase { [HttpGet("tenants")] [Authorize(Policy = BackendPermissions.PlatformTenantManage)] [EndpointSummary("查询平台租户列表")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> Tenants( [FromQuery] PlatformAdminQueryDto query, CancellationToken cancellationToken) { return Ok(await service.GetTenantsAsync(actorResolver.Resolve(), query.ToQuery(), cancellationToken)); } [HttpPost("tenants")] [Authorize(Policy = BackendPermissions.PlatformTenantManage)] [EndpointSummary("创建平台租户")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> CreateTenant( CreatePlatformTenantDto request, [FromHeader(Name = "Idempotency-Key")] [Required] string idempotencyKey, CancellationToken cancellationToken) { return Ok(await service.CreateTenantAsync( actorResolver.Resolve(), request.ToCommand(idempotencyKey), cancellationToken)); } [HttpPut("tenants/{tenantId:guid}/primary-domain")] [Authorize(Policy = BackendPermissions.PlatformTenantManage)] [EndpointSummary("更正租户主域名")] public Task ReplacePrimaryDomain( Guid tenantId, ReplacePlatformPrimaryDomainDto request, CancellationToken cancellationToken) { return service.ReplacePrimaryDomainAsync(actorResolver.Resolve(), request.ToCommand(tenantId), cancellationToken); } [HttpPost("tenants/{tenantId:guid}/owner-activation-links")] [Authorize(Policy = BackendPermissions.PlatformTenantManage)] [EndpointSummary("一次性领取租户 Owner 激活链接")] [EndpointDescription("仅在主域名和试用/订阅有效时签发;幂等重放不会再次返回明文链接。")] public Task IssueOwnerActivationLink( Guid tenantId, IssuePlatformOwnerActivationLinkDto request, [FromHeader(Name = "Idempotency-Key")] [Required] string idempotencyKey, CancellationToken cancellationToken) { return service.IssueOwnerActivationLinkAsync( actorResolver.Resolve(), request.ToCommand(tenantId, idempotencyKey), cancellationToken); } [HttpGet("tenants/{tenantId:guid}/billing-policy")] [Authorize(Policy = BackendPermissions.PlatformTenantManage)] [EndpointSummary("查询租户收款策略")] public Task GetBillingPolicy(Guid tenantId, CancellationToken cancellationToken) { return service.GetTenantBillingPolicyAsync(actorResolver.Resolve(), tenantId, cancellationToken); } [HttpPut("tenants/{tenantId:guid}/billing-policy")] [Authorize(Policy = BackendPermissions.PlatformTenantManage)] [EndpointSummary("更新租户收款策略")] public Task UpsertBillingPolicy( Guid tenantId, UpsertTenantBillingPolicyDto request, CancellationToken cancellationToken) { return service.UpsertTenantBillingPolicyAsync(actorResolver.Resolve(), request.ToCommand(tenantId), cancellationToken); } [HttpGet("tenants/detail")] [Authorize(Policy = BackendPermissions.PlatformTenantManage)] [EndpointSummary("查询平台租户详情")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> TenantDetail( [FromQuery] Guid tenantId, CancellationToken cancellationToken) { return Ok(await service.GetTenantDetailAsync(actorResolver.Resolve(), tenantId, cancellationToken)); } [HttpPatch("tenants/status")] [Authorize(Policy = BackendPermissions.PlatformTenantManage)] [EndpointSummary("更新租户业务状态")] [PlatformOperationRisk("critical", PlatformApprovalPolicyCodes.TenantArchive)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status202Accepted)] public async Task> TenantStatus( UpdatePlatformTenantStatusDto request, [FromHeader(Name = "Idempotency-Key")] [Required] string idempotencyKey, CancellationToken cancellationToken) { var result = await approvalService.UpdateTenantStatusAsync(actorResolver.Resolve(), request.ToCommand(), idempotencyKey, cancellationToken); return result.ExecutionStatus == "pending_approval" ? Accepted(result) : Ok(result); } [HttpPut("tenants/billing-profile")] [Authorize(Policy = BackendPermissions.PlatformTenantManage)] [EndpointSummary("保存租户账务与开票资料")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> BillingProfile( UpsertPlatformTenantBillingProfileDto request, CancellationToken cancellationToken) { return Ok(await service.UpsertTenantBillingProfileAsync(actorResolver.Resolve(), request.ToCommand(), cancellationToken)); } }