feat: complete phase six backoffice operations

This commit is contained in:
2026-07-28 14:31:43 +08:00
parent 747ff59d76
commit 99e4e43122
31 changed files with 23504 additions and 26 deletions

View File

@@ -7,6 +7,7 @@ using Tiku.Api.Contracts;
using Tiku.Application.Commerce;
using Tiku.Application.Security;
using Tiku.Application.Tenancy;
using Tiku.Domain.Commerce;
namespace Tiku.Api.Controllers;
@@ -16,6 +17,7 @@ namespace Tiku.Api.Controllers;
[Route("api/commerce")]
public sealed class CommerceController(
ICommerceService commerceService,
ICommerceAdminService commerceAdminService,
ICurrentUser currentUser,
ITenantContext currentTenant,
ITenantContextInitializer tenantInitializer,
@@ -151,6 +153,36 @@ public sealed class CommerceController(
cancellationToken));
}
[AllowAnonymous]
[HttpPost("refunds/notify/wechat_pay")]
[EndpointSummary("微信退款结果回调")]
[ProducesResponseType<CommerceRefundRequest>(StatusCodes.Status200OK)]
public async Task<ActionResult<CommerceRefundRequest>> WechatRefundNotify(
[FromQuery] string? tenantCode,
RefundNotificationDto request,
CancellationToken cancellationToken)
{
return Ok(await commerceAdminService.ProcessRefundNotificationAsync(
await ResolveNotificationTenantAsync(tenantCode, cancellationToken),
request.ToCommand(PaymentProviders.WechatPay),
cancellationToken));
}
[AllowAnonymous]
[HttpPost("refunds/notify/alipay")]
[EndpointSummary("支付宝退款结果回调")]
[ProducesResponseType<CommerceRefundRequest>(StatusCodes.Status200OK)]
public async Task<ActionResult<CommerceRefundRequest>> AlipayRefundNotify(
[FromQuery] string? tenantCode,
RefundNotificationDto request,
CancellationToken cancellationToken)
{
return Ok(await commerceAdminService.ProcessRefundNotificationAsync(
await ResolveNotificationTenantAsync(tenantCode, cancellationToken),
request.ToCommand(PaymentProviders.Alipay),
cancellationToken));
}
private async Task<Guid> ResolveNotificationTenantAsync(
string? tenantCode,
CancellationToken cancellationToken)

View File

@@ -0,0 +1,266 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Tiku.Api.Contracts;
using Tiku.Application.PlatformAdmin;
using Tiku.Application.Security;
using Tiku.Domain.Platform;
namespace Tiku.Api.Controllers;
[ApiController]
[Authorize(Policy = BackendPermissions.PlatformDashboardView)]
[Produces("application/json")]
[Route("api/platform-admin")]
public sealed class PlatformAdminController(
IPlatformAdminService platformAdminService,
ICurrentUser currentUser) : ControllerBase
{
[HttpGet("overview")]
[EndpointSummary("查询平台经营概览")]
[ProducesResponseType<PlatformOverview>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformOverview>> Overview(CancellationToken cancellationToken)
{
return Ok(await platformAdminService.GetOverviewAsync(ResolveActor(), cancellationToken));
}
[HttpGet("tenants")]
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
[EndpointSummary("查询平台租户列表")]
[ProducesResponseType<PlatformTenantList>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformTenantList>> Tenants(
[FromQuery] PlatformAdminQueryDto query,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.GetTenantsAsync(ResolveActor(), query.ToQuery(), cancellationToken));
}
[HttpPost("tenants")]
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
[EndpointSummary("创建平台租户")]
[ProducesResponseType<PlatformTenantItem>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformTenantItem>> CreateTenant(
CreatePlatformTenantDto request,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.CreateTenantAsync(ResolveActor(), request.ToCommand(), cancellationToken));
}
[HttpGet("tenants/detail")]
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
[EndpointSummary("查询平台租户详情")]
[ProducesResponseType<PlatformTenantDetail>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformTenantDetail>> TenantDetail(
[FromQuery] Guid tenantId,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.GetTenantDetailAsync(ResolveActor(), tenantId, cancellationToken));
}
[HttpPatch("tenants/status")]
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
[EndpointSummary("更新租户业务与账务状态")]
[ProducesResponseType<PlatformTenantItem>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformTenantItem>> TenantStatus(
UpdatePlatformTenantStatusDto request,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.UpdateTenantStatusAsync(ResolveActor(), request.ToCommand(), cancellationToken));
}
[HttpPut("tenants/billing-profile")]
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
[EndpointSummary("保存租户账务与开票资料")]
[ProducesResponseType<TenantBillingProfileItem>(StatusCodes.Status200OK)]
public async Task<ActionResult<TenantBillingProfileItem>> BillingProfile(
UpsertPlatformTenantBillingProfileDto request,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.UpsertTenantBillingProfileAsync(ResolveActor(), request.ToCommand(), cancellationToken));
}
[HttpGet("plans")]
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
[EndpointSummary("查询平台 SaaS 套餐")]
[ProducesResponseType<PlatformPlanList>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformPlanList>> Plans(
[FromQuery] PlatformAdminQueryDto query,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.GetPlansAsync(ResolveActor(), query.ToQuery(), cancellationToken));
}
[HttpPost("subscriptions")]
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
[EndpointSummary("创建或调整租户订阅")]
[ProducesResponseType<PlatformTenantSubscriptionItem>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformTenantSubscriptionItem>> UpsertSubscription(
UpsertPlatformSubscriptionDto request,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.UpsertSubscriptionAsync(ResolveActor(), request.ToCommand(), cancellationToken));
}
[HttpGet("domains")]
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
[EndpointSummary("查询租户域名状态")]
[ProducesResponseType<PlatformDomainList>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformDomainList>> Domains(
[FromQuery] PlatformAdminQueryDto query,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.GetDomainsAsync(ResolveActor(), query.ToQuery(), cancellationToken));
}
[HttpPost("domains/{domainId:guid}/recheck")]
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
[EndpointSummary("重新触发租户域名 DNS/TLS 验证")]
[ProducesResponseType<PlatformDomainRecheckResult>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformDomainRecheckResult>> RecheckDomain(
Guid domainId,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.RecheckDomainAsync(ResolveActor(), domainId, cancellationToken));
}
[HttpGet("staff")]
[Authorize(Policy = BackendPermissions.PlatformStaffManage)]
[EndpointSummary("查询平台员工列表")]
[ProducesResponseType<PlatformStaffList>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformStaffList>> Staff(
[FromQuery] PlatformAdminQueryDto query,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.GetStaffAsync(ResolveActor(), query.ToQuery(), cancellationToken));
}
[HttpPut("staff")]
[Authorize(Policy = BackendPermissions.PlatformStaffManage)]
[EndpointSummary("创建或更新平台员工")]
[ProducesResponseType<PlatformStaffItem>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformStaffItem>> UpsertStaff(
UpsertPlatformStaffDto request,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.UpsertStaffAsync(ResolveActor(), request.ToCommand(), cancellationToken));
}
[HttpPatch("staff/status")]
[Authorize(Policy = BackendPermissions.PlatformStaffManage)]
[EndpointSummary("启用或禁用平台员工")]
[ProducesResponseType<PlatformStaffItem>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformStaffItem>> StaffStatus(
UpdatePlatformStaffStatusDto request,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.UpdateStaffStatusAsync(ResolveActor(), request.ToCommand(), cancellationToken));
}
[HttpGet("audit-logs")]
[Authorize(Policy = BackendPermissions.PlatformAuditView)]
[EndpointSummary("查询平台审计日志")]
[ProducesResponseType<PlatformAuditLogList>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformAuditLogList>> AuditLogs(
[FromQuery] PlatformAdminQueryDto query,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.GetAuditLogsAsync(ResolveActor(), query.ToQuery(), cancellationToken));
}
[HttpGet("audit-alerts")]
[Authorize(Policy = BackendPermissions.PlatformAuditView)]
[EndpointSummary("查询平台审计告警")]
[ProducesResponseType<PlatformAuditAlertList>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformAuditAlertList>> AuditAlerts(
[FromQuery] PlatformAdminQueryDto query,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.GetAuditAlertsAsync(ResolveActor(), query.ToQuery(), cancellationToken));
}
[HttpPost("audit-alerts/status")]
[Authorize(Policy = BackendPermissions.PlatformAuditView)]
[EndpointSummary("更新平台审计告警状态")]
[ProducesResponseType<PlatformAuditAlert>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformAuditAlert>> AuditAlertStatus(
UpdatePlatformAuditAlertStatusDto request,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.UpdateAuditAlertStatusAsync(ResolveActor(), request.ToCommand(), cancellationToken));
}
[HttpGet("dunning-notification-channels")]
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
[EndpointSummary("查询平台催缴通知渠道")]
[ProducesResponseType<PlatformDunningChannelList>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformDunningChannelList>> DunningChannels(
[FromQuery] PlatformAdminQueryDto query,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.GetDunningChannelsAsync(ResolveActor(), query.ToQuery(), cancellationToken));
}
[HttpPut("dunning-notification-channels")]
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
[EndpointSummary("创建或更新平台催缴通知渠道")]
[ProducesResponseType<PlatformDunningChannelItem>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformDunningChannelItem>> UpsertDunningChannel(
UpsertPlatformDunningChannelDto request,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.UpsertDunningChannelAsync(ResolveActor(), request.ToCommand(), cancellationToken));
}
[HttpPost("dunning-notification-channels/disable")]
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
[EndpointSummary("禁用平台催缴通知渠道")]
[ProducesResponseType<PlatformDunningChannelItem>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformDunningChannelItem>> DisableDunningChannel(
DisablePlatformDunningChannelDto request,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.DisableDunningChannelAsync(ResolveActor(), request.ToCommand(), cancellationToken));
}
[HttpGet("dunning-notification-events")]
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
[EndpointSummary("查询平台催缴通知事件")]
[ProducesResponseType<PlatformDunningEventList>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformDunningEventList>> DunningEvents(
[FromQuery] PlatformAdminQueryDto query,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.GetDunningEventsAsync(ResolveActor(), query.ToQuery(), cancellationToken));
}
[HttpGet("dunning-notification-events/detail")]
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
[EndpointSummary("查询平台催缴通知事件详情")]
[ProducesResponseType<PlatformDunningEventItem>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformDunningEventItem>> DunningEventDetail(
[FromQuery] Guid eventId,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.GetDunningEventDetailAsync(ResolveActor(), eventId, cancellationToken));
}
[HttpPost("dunning-notification-events/retry")]
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
[EndpointSummary("重新标记平台催缴通知事件待发送")]
[ProducesResponseType<PlatformDunningEventItem>(StatusCodes.Status200OK)]
public async Task<ActionResult<PlatformDunningEventItem>> RetryDunningEvent(
RetryPlatformDunningEventDto request,
CancellationToken cancellationToken)
{
return Ok(await platformAdminService.RetryDunningEventAsync(ResolveActor(), request.ToCommand(), cancellationToken));
}
private PlatformAdminActor ResolveActor()
{
if (currentUser.UserId is not { } userId)
{
throw new PlatformAdminException("Platform admin actor was not resolved.", "platform_access_denied");
}
return new PlatformAdminActor(userId);
}
}

View File

@@ -17,6 +17,15 @@ public sealed class TenantAdminDirectController(
ICurrentUser currentUser,
ITenantContext currentTenant) : ControllerBase
{
[HttpGet("overview")]
[Authorize(Policy = BackendPermissions.TenantDashboardView)]
[EndpointSummary("查询租户后台运营概览")]
[ProducesResponseType<TenantAdminOverviewItem>(StatusCodes.Status200OK)]
public async Task<ActionResult<TenantAdminOverviewItem>> GetOverview(CancellationToken cancellationToken)
{
return Ok(await tenantAdminService.GetOverviewAsync(ResolveActor(), cancellationToken));
}
[HttpGet("classes")]
[Authorize(Policy = BackendPermissions.TenantStudentManage)]
[EndpointSummary("查询租户班级")]
@@ -116,6 +125,117 @@ public sealed class TenantAdminDirectController(
return Ok(await tenantAdminService.UpdateStudentStatusAsync(ResolveActor(), request.ToCommand(), cancellationToken));
}
[HttpPost("students/import/preview")]
[Authorize(Policy = BackendPermissions.TenantStudentManage)]
[EndpointSummary("预览学生批量导入")]
[ProducesResponseType<TenantAdminStudentImportPreview>(StatusCodes.Status200OK)]
public async Task<ActionResult<TenantAdminStudentImportPreview>> PreviewStudentImport(
TenantAdminStudentImportDto request,
CancellationToken cancellationToken)
{
return Ok(await tenantAdminService.PreviewStudentImportAsync(ResolveActor(), request.ToCommand(), cancellationToken));
}
[HttpPost("students/import")]
[Authorize(Policy = BackendPermissions.TenantStudentManage)]
[EndpointSummary("提交学生批量导入")]
[ProducesResponseType<TenantAdminStudentImportResult>(StatusCodes.Status200OK)]
public async Task<ActionResult<TenantAdminStudentImportResult>> ImportStudents(
TenantAdminStudentImportDto request,
CancellationToken cancellationToken)
{
return Ok(await tenantAdminService.ImportStudentsAsync(ResolveActor(), request.ToCommand(), cancellationToken));
}
[HttpPost("students/bulk-assign-class")]
[Authorize(Policy = BackendPermissions.TenantStudentManage)]
[EndpointSummary("批量分班")]
[ProducesResponseType<TenantAdminBulkOperationResult>(StatusCodes.Status200OK)]
public async Task<ActionResult<TenantAdminBulkOperationResult>> BulkAssignClass(
TenantAdminBulkAssignClassDto request,
CancellationToken cancellationToken)
{
return Ok(await tenantAdminService.BulkAssignClassAsync(ResolveActor(), request.ToCommand(), cancellationToken));
}
[HttpPost("students/bulk-status")]
[Authorize(Policy = BackendPermissions.TenantStudentManage)]
[EndpointSummary("批量调整学生状态")]
[ProducesResponseType<TenantAdminBulkOperationResult>(StatusCodes.Status200OK)]
public async Task<ActionResult<TenantAdminBulkOperationResult>> BulkStudentStatus(
TenantAdminBulkStatusDto request,
CancellationToken cancellationToken)
{
return Ok(await tenantAdminService.BulkUpdateStudentStatusAsync(ResolveActor(), request.ToCommand(), cancellationToken));
}
[HttpGet("students/supervision/rules")]
[Authorize(Policy = BackendPermissions.TenantStudentManage)]
[EndpointSummary("查询学习督导规则")]
[ProducesResponseType<CatalogList<TenantSupervisionRuleItem>>(StatusCodes.Status200OK)]
public async Task<ActionResult<CatalogList<TenantSupervisionRuleItem>>> SupervisionRules(CancellationToken cancellationToken)
{
return Ok(await tenantAdminService.GetSupervisionRulesAsync(ResolveActor(), cancellationToken));
}
[HttpPut("students/supervision/rules")]
[Authorize(Policy = BackendPermissions.TenantStudentManage)]
[EndpointSummary("新增或更新学习督导规则")]
[ProducesResponseType<ContentManagementResult<TenantSupervisionRuleItem>>(StatusCodes.Status200OK)]
public async Task<ActionResult<ContentManagementResult<TenantSupervisionRuleItem>>> UpsertSupervisionRule(
UpsertTenantSupervisionRuleDto request,
CancellationToken cancellationToken)
{
return Ok(await tenantAdminService.UpsertSupervisionRuleAsync(ResolveActor(), request.ToCommand(), cancellationToken));
}
[HttpGet("students/supervision/preview")]
[Authorize(Policy = BackendPermissions.TenantStudentManage)]
[EndpointSummary("预览学习风险学生")]
[ProducesResponseType<TenantSupervisionPreview>(StatusCodes.Status200OK)]
public async Task<ActionResult<TenantSupervisionPreview>> PreviewSupervision(CancellationToken cancellationToken)
{
return Ok(await tenantAdminService.PreviewSupervisionAsync(ResolveActor(), cancellationToken));
}
[HttpPost("students/supervision/generate")]
[Authorize(Policy = BackendPermissions.TenantStudentManage)]
[EndpointSummary("批量生成学习督导跟进任务")]
[ProducesResponseType<TenantSupervisionGenerateResult>(StatusCodes.Status200OK)]
public async Task<ActionResult<TenantSupervisionGenerateResult>> GenerateSupervision(
TenantSupervisionGenerateDto request,
CancellationToken cancellationToken)
{
return Ok(await tenantAdminService.GenerateSupervisionFollowupsAsync(ResolveActor(), request.ToCommand(), cancellationToken));
}
[HttpGet("student-followups/report")]
[Authorize(Policy = BackendPermissions.TenantStudentManage)]
[EndpointSummary("查询学生跟进统计报表")]
[ProducesResponseType<TenantFollowupReport>(StatusCodes.Status200OK)]
public async Task<ActionResult<TenantFollowupReport>> FollowupReport(CancellationToken cancellationToken)
{
return Ok(await tenantAdminService.GetFollowupReportAsync(ResolveActor(), cancellationToken));
}
[HttpGet("feedbacks/report")]
[Authorize(Policy = BackendPermissions.TenantStudentManage)]
[EndpointSummary("查询反馈处理统计报表")]
[ProducesResponseType<TenantFeedbackReport>(StatusCodes.Status200OK)]
public async Task<ActionResult<TenantFeedbackReport>> FeedbackReport(CancellationToken cancellationToken)
{
return Ok(await tenantAdminService.GetFeedbackReportAsync(ResolveActor(), cancellationToken));
}
[HttpGet("points/risk-report")]
[Authorize(Policy = BackendPermissions.TenantStudentManage)]
[EndpointSummary("查询积分风险统计报表")]
[ProducesResponseType<TenantPointRiskReport>(StatusCodes.Status200OK)]
public async Task<ActionResult<TenantPointRiskReport>> PointRiskReport(CancellationToken cancellationToken)
{
return Ok(await tenantAdminService.GetPointRiskReportAsync(ResolveActor(), cancellationToken));
}
[HttpGet("student-notes")]
[Authorize(Policy = BackendPermissions.TenantStudentManage)]
[EndpointSummary("查询学生备注")]

View File

@@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Tiku.Api.Contracts;
using Tiku.Application.Commerce;
using Tiku.Application.Jobs;
using Tiku.Application.Security;
using Tiku.Domain.Commerce;
@@ -374,6 +375,34 @@ public sealed class TenantCommerceController(
cancellationToken));
}
[HttpGet("reconciliation/items")]
[Authorize(Policy = TikuPolicies.TenantCommerceOperateAllScope)]
[EndpointSummary("查询对账明细")]
[ProducesResponseType<TenantReconciliationItemList>(StatusCodes.Status200OK)]
public async Task<ActionResult<TenantReconciliationItemList>> ReconciliationItems(
[FromQuery] Guid batchId,
CancellationToken cancellationToken)
{
return Ok(await commerceAdminService.GetReconciliationItemsAsync(
ResolveActor(),
batchId,
cancellationToken));
}
[HttpGet("reconciliation/issues/events")]
[Authorize(Policy = TikuPolicies.TenantCommerceOperateAllScope)]
[EndpointSummary("查询对账工单事件")]
[ProducesResponseType<TenantReconciliationIssueEventList>(StatusCodes.Status200OK)]
public async Task<ActionResult<TenantReconciliationIssueEventList>> ReconciliationIssueEvents(
[FromQuery] Guid issueId,
CancellationToken cancellationToken)
{
return Ok(await commerceAdminService.GetReconciliationIssueEventsAsync(
ResolveActor(),
issueId,
cancellationToken));
}
[HttpPost("reconciliation/issues/status")]
[Authorize(Policy = TikuPolicies.TenantCommerceOperateAllScope)]
[EndpointSummary("更新对账异常状态")]
@@ -388,6 +417,154 @@ public sealed class TenantCommerceController(
cancellationToken));
}
[HttpGet("adjustment-vouchers")]
[Authorize(Policy = TikuPolicies.TenantCommerceOperateAllScope)]
[EndpointSummary("查询调账凭证")]
[ProducesResponseType<TenantAdjustmentVoucherList>(StatusCodes.Status200OK)]
public async Task<ActionResult<TenantAdjustmentVoucherList>> AdjustmentVouchers(
[FromQuery] TenantCommerceQueryDto query,
CancellationToken cancellationToken)
{
return Ok(await commerceAdminService.GetAdjustmentVouchersAsync(
ResolveActor(),
ToQuery(query),
cancellationToken));
}
[HttpGet("adjustment-vouchers/detail")]
[Authorize(Policy = TikuPolicies.TenantCommerceOperateAllScope)]
[EndpointSummary("查询调账凭证详情")]
[ProducesResponseType<CommerceAdjustmentVoucher>(StatusCodes.Status200OK)]
public async Task<ActionResult<CommerceAdjustmentVoucher>> AdjustmentVoucherDetail(
[FromQuery] Guid voucherId,
CancellationToken cancellationToken)
{
return Ok(await commerceAdminService.GetAdjustmentVoucherAsync(
ResolveActor(),
voucherId,
cancellationToken));
}
[HttpPost("adjustment-vouchers")]
[Authorize(Policy = TikuPolicies.TenantCommerceOperateAllScope)]
[EndpointSummary("创建调账凭证")]
[ProducesResponseType<CommerceAdjustmentVoucher>(StatusCodes.Status200OK)]
public async Task<ActionResult<CommerceAdjustmentVoucher>> CreateAdjustmentVoucher(
CreateAdjustmentVoucherDto request,
CancellationToken cancellationToken)
{
return Ok(await commerceAdminService.CreateAdjustmentVoucherAsync(
ResolveActor(),
request.ToCommand(),
cancellationToken));
}
[HttpPost("adjustment-vouchers/status")]
[Authorize(Policy = TikuPolicies.TenantCommerceOperateAllScope)]
[EndpointSummary("审核或关闭调账凭证")]
[ProducesResponseType<CommerceAdjustmentVoucher>(StatusCodes.Status200OK)]
public async Task<ActionResult<CommerceAdjustmentVoucher>> UpdateAdjustmentVoucherStatus(
UpdateAdjustmentVoucherStatusDto request,
CancellationToken cancellationToken)
{
return Ok(await commerceAdminService.UpdateAdjustmentVoucherStatusAsync(
ResolveActor(),
request.ToCommand(),
cancellationToken));
}
[HttpGet("adjustment-vouchers/events")]
[Authorize(Policy = TikuPolicies.TenantCommerceOperateAllScope)]
[EndpointSummary("查询调账凭证事件")]
[ProducesResponseType<TenantAdjustmentVoucherEventList>(StatusCodes.Status200OK)]
public async Task<ActionResult<TenantAdjustmentVoucherEventList>> AdjustmentVoucherEvents(
[FromQuery] Guid voucherId,
CancellationToken cancellationToken)
{
return Ok(await commerceAdminService.GetAdjustmentVoucherEventsAsync(
ResolveActor(),
voucherId,
cancellationToken));
}
[HttpGet("adjustment-vouchers/report")]
[Authorize(Policy = TikuPolicies.TenantCommerceOperateAllScope)]
[EndpointSummary("查询调账统计报告")]
[ProducesResponseType<TenantAdjustmentReport>(StatusCodes.Status200OK)]
public async Task<ActionResult<TenantAdjustmentReport>> AdjustmentVoucherReport(CancellationToken cancellationToken)
{
return Ok(await commerceAdminService.GetAdjustmentReportAsync(
ResolveActor(),
cancellationToken));
}
[HttpGet("reconciliation/anomalies")]
[Authorize(Policy = TikuPolicies.TenantCommerceOperateAllScope)]
[EndpointSummary("查询对账异常汇总")]
[ProducesResponseType<TenantCommerceAnomalySummary>(StatusCodes.Status200OK)]
public async Task<ActionResult<TenantCommerceAnomalySummary>> ReconciliationAnomalies(CancellationToken cancellationToken)
{
return Ok(await commerceAdminService.GetAnomalySummaryAsync(
ResolveActor(),
cancellationToken));
}
[HttpPost("reconciliation/preview")]
[Authorize(Policy = TikuPolicies.TenantCommerceOperateAllScope)]
[EndpointSummary("预览支付渠道账单对账")]
[ProducesResponseType<ReconciliationImportPreview>(StatusCodes.Status200OK)]
public async Task<ActionResult<ReconciliationImportPreview>> PreviewReconciliation(
PreviewReconciliationImportDto request,
CancellationToken cancellationToken)
{
return Ok(await commerceAdminService.PreviewReconciliationImportAsync(
ResolveActor(),
request.ToPreviewCommand(),
cancellationToken));
}
[HttpPost("reconciliation/import")]
[Authorize(Policy = TikuPolicies.TenantCommerceOperateAllScope)]
[EndpointSummary("导入支付渠道账单并创建对账批次")]
[ProducesResponseType<CommerceReconciliationBatch>(StatusCodes.Status200OK)]
public async Task<ActionResult<CommerceReconciliationBatch>> ImportReconciliation(
PreviewReconciliationImportDto request,
CancellationToken cancellationToken)
{
return Ok(await commerceAdminService.ImportReconciliationAsync(
ResolveActor(),
request.ToImportCommand(),
cancellationToken));
}
[HttpGet("reconciliation/provider-bills/jobs")]
[Authorize(Policy = TikuPolicies.TenantCommerceOperateAllScope)]
[EndpointSummary("查询渠道账单下载任务")]
[ProducesResponseType<IReadOnlyCollection<BackgroundJobItem>>(StatusCodes.Status200OK)]
public async Task<ActionResult<IReadOnlyCollection<BackgroundJobItem>>> ProviderBillJobs(
[FromQuery] TenantCommerceQueryDto query,
CancellationToken cancellationToken)
{
return Ok(await commerceAdminService.GetProviderBillJobsAsync(
ResolveActor(),
ToQuery(query),
cancellationToken));
}
[HttpPost("reconciliation/provider-bills/request")]
[Authorize(Policy = TikuPolicies.TenantCommerceOperateAllScope)]
[EndpointSummary("创建渠道官方账单下载任务")]
[ProducesResponseType<BackgroundJobItem>(StatusCodes.Status200OK)]
public async Task<ActionResult<BackgroundJobItem>> RequestProviderBill(
RequestProviderBillJobDto request,
CancellationToken cancellationToken)
{
return Ok(await commerceAdminService.RequestProviderBillJobAsync(
ResolveActor(),
request.ToCommand(),
cancellationToken));
}
private CommerceAdminActor ResolveActor()
{
if (currentTenant.TenantId is null || currentUser.UserId is null)