using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Tiku.Api.Contracts; using Tiku.Application.PlatformBilling; using Tiku.Application.Security; using Tiku.Domain.Platform; namespace Tiku.Api.Controllers; [ApiController] [Route("api/platform-admin/saas")] [Authorize(Policy = TikuPolicies.PlatformBackofficeBootstrap)] public sealed class PlatformSaasController( ISaasCatalogAdminService catalogService, IPlatformBillingAdminService billingService, ICurrentUser currentUser) : ControllerBase { [HttpGet("catalog")] [Authorize(Policy = BackendPermissions.PlatformSaasCatalogManage)] public Task Catalog(CancellationToken cancellationToken) => catalogService.GetCatalogAsync(Actor(), cancellationToken); [HttpPut("features")] [Authorize(Policy = BackendPermissions.PlatformSaasCatalogManage)] public Task UpsertFeature(UpsertSaasFeatureDto request, CancellationToken cancellationToken) => catalogService.UpsertFeatureAsync(Actor(), request.ToCommand(), cancellationToken); [HttpPut("feature-limits")] [Authorize(Policy = BackendPermissions.PlatformSaasCatalogManage)] public Task UpsertFeatureLimit( UpsertSaasFeatureLimitDto request, CancellationToken cancellationToken) => catalogService.UpsertLimitDefinitionAsync(Actor(), request.ToCommand(), cancellationToken); [HttpPut("offerings")] [Authorize(Policy = BackendPermissions.PlatformSaasCatalogManage)] public Task UpsertOffering(UpsertSaasOfferingDto request, CancellationToken cancellationToken) => catalogService.UpsertOfferingAsync(Actor(), request.ToCommand(), cancellationToken); [HttpPut("offering-versions")] [Authorize(Policy = BackendPermissions.PlatformSaasCatalogManage)] public Task UpsertVersion(UpsertSaasOfferingVersionDto request, CancellationToken cancellationToken) => catalogService.UpsertDraftVersionAsync(Actor(), request.ToCommand(), cancellationToken); [HttpPost("offering-versions/{versionId:guid}/publish")] [Authorize(Policy = BackendPermissions.PlatformSaasCatalogManage)] public Task PublishVersion(Guid versionId, CancellationToken cancellationToken) => catalogService.PublishVersionAsync(Actor(), versionId, cancellationToken); [HttpPost("offering-versions/{versionId:guid}/clone")] [Authorize(Policy = BackendPermissions.PlatformSaasCatalogManage)] public Task CloneVersion(Guid versionId, CancellationToken cancellationToken) => catalogService.CloneVersionAsync(Actor(), versionId, cancellationToken); [HttpPost("offering-versions/{versionId:guid}/retire")] [Authorize(Policy = BackendPermissions.PlatformSaasCatalogManage)] public Task RetireVersion(Guid versionId, CancellationToken cancellationToken) => catalogService.RetireVersionAsync(Actor(), versionId, cancellationToken); [HttpGet("orders")] [Authorize(Policy = BackendPermissions.PlatformSaasBillingManage)] public Task> Orders(Guid? tenantId, string? status, int limit = 100, CancellationToken cancellationToken = default) => billingService.GetOrdersAsync(Actor(), new PlatformBillingAdminQuery(tenantId, status, limit), cancellationToken); [HttpGet("payments")] [Authorize(Policy = BackendPermissions.PlatformSaasBillingManage)] public Task> Payments(Guid? tenantId, string? status, int limit = 100, CancellationToken cancellationToken = default) => billingService.GetPaymentsAsync(Actor(), new PlatformBillingAdminQuery(tenantId, status, limit), cancellationToken); [HttpGet("refunds")] [Authorize(Policy = BackendPermissions.PlatformSaasBillingManage)] public Task> Refunds(Guid? tenantId, string? status, int limit = 100, CancellationToken cancellationToken = default) => billingService.GetRefundsAsync(Actor(), new PlatformBillingAdminQuery(tenantId, status, limit), cancellationToken); [HttpGet("invoices")] [Authorize(Policy = BackendPermissions.PlatformSaasBillingManage)] public Task> Invoices(Guid? tenantId, string? status, int limit = 100, CancellationToken cancellationToken = default) => billingService.GetInvoicesAsync(Actor(), new PlatformBillingAdminQuery(tenantId, status, limit), cancellationToken); [HttpGet("subscriptions")] [Authorize(Policy = BackendPermissions.PlatformSaasBillingManage)] public Task> Subscriptions(Guid? tenantId, string? status, int limit = 100, CancellationToken cancellationToken = default) => billingService.GetSubscriptionsAsync(Actor(), new PlatformBillingAdminQuery(tenantId, status, limit), cancellationToken); [HttpPost("payments/manual/confirm")] [Authorize(Policy = BackendPermissions.PlatformSaasBillingManage)] public Task ConfirmManualPayment(ConfirmManualPlatformPaymentDto request, CancellationToken cancellationToken) => billingService.ConfirmManualPaymentAsync(Actor(), request.ToCommand(), cancellationToken); [HttpPut("tenant-feature-overrides")] [Authorize(Policy = BackendPermissions.PlatformSaasBillingManage)] public Task UpsertFeatureOverride(UpsertTenantFeatureOverrideDto request, CancellationToken cancellationToken) => billingService.UpsertFeatureOverrideAsync(Actor(), request.ToCommand(), cancellationToken); private SaasCatalogActor Actor() => currentUser.UserId is { } userId ? new SaasCatalogActor(userId) : throw new PlatformBillingException("Platform actor was not resolved.", "platform_access_denied"); }