forked from xiongyuxing/tiku-backend.net
feat: complete phase six backoffice operations
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.Text.Json;
|
||||
using Tiku.Application.Jobs;
|
||||
using Tiku.Domain.Commerce;
|
||||
using Tiku.Domain.Tenancy;
|
||||
|
||||
@@ -180,6 +181,81 @@ public sealed record CreateReconciliationBatchCommand(
|
||||
|
||||
public sealed record TenantReconciliationBatchList(IReadOnlyCollection<CommerceReconciliationBatch> Items);
|
||||
public sealed record TenantReconciliationIssueList(IReadOnlyCollection<CommerceReconciliationIssue> Items);
|
||||
public sealed record TenantReconciliationItemList(IReadOnlyCollection<CommerceReconciliationItem> Items);
|
||||
public sealed record TenantReconciliationIssueEventList(IReadOnlyCollection<CommerceReconciliationIssueEvent> Items);
|
||||
public sealed record TenantCommerceAnomalySummary(
|
||||
int OpenRefundCount,
|
||||
int ProcessingRefundCount,
|
||||
int OpenReconciliationIssueCount,
|
||||
int FailedReconciliationBatchCount,
|
||||
int PendingPaymentCount,
|
||||
int PaymentMismatchCount);
|
||||
|
||||
public sealed record CreateAdjustmentVoucherCommand(
|
||||
Guid? IssueId,
|
||||
Guid? BatchId,
|
||||
Guid? ItemId,
|
||||
Guid? OrderId,
|
||||
Guid? PaymentId,
|
||||
Guid? RefundRequestId,
|
||||
CommerceAdjustmentDirection Direction,
|
||||
int AmountCents,
|
||||
string? Currency,
|
||||
string Reason,
|
||||
string? ProofAssetKey,
|
||||
JsonElement Metadata);
|
||||
|
||||
public sealed record UpdateAdjustmentVoucherStatusCommand(
|
||||
Guid VoucherId,
|
||||
CommerceAdjustmentVoucherStatus Status,
|
||||
string? Note);
|
||||
|
||||
public sealed record TenantAdjustmentVoucherList(IReadOnlyCollection<CommerceAdjustmentVoucher> Items);
|
||||
public sealed record TenantAdjustmentVoucherEventList(IReadOnlyCollection<CommerceAdjustmentVoucherEvent> Items);
|
||||
public sealed record TenantAdjustmentReport(
|
||||
int DraftCount,
|
||||
int PendingReviewCount,
|
||||
int ApprovedCount,
|
||||
int ClosedCount,
|
||||
int IncreaseRevenueCents,
|
||||
int DecreaseRevenueCents);
|
||||
|
||||
public sealed record PreviewReconciliationImportCommand(
|
||||
string Provider,
|
||||
DateOnly BillDate,
|
||||
ReconciliationBillType BillType,
|
||||
string SourceName,
|
||||
JsonElement Rows);
|
||||
|
||||
public sealed record ReconciliationImportPreview(
|
||||
int TotalCount,
|
||||
int PaymentCount,
|
||||
int RefundCount,
|
||||
int InvalidCount,
|
||||
int AmountCents,
|
||||
int RefundAmountCents,
|
||||
string SourceHash);
|
||||
|
||||
public sealed record ImportReconciliationCommand(
|
||||
string Provider,
|
||||
DateOnly BillDate,
|
||||
ReconciliationBillType BillType,
|
||||
string SourceName,
|
||||
JsonElement Rows);
|
||||
|
||||
public sealed record RequestProviderBillJobCommand(
|
||||
string Provider,
|
||||
DateOnly BillDate,
|
||||
ReconciliationBillType BillType,
|
||||
DateTimeOffset? RunAfter = null);
|
||||
|
||||
public sealed record RefundNotificationCommand(
|
||||
string Provider,
|
||||
string RefundNo,
|
||||
string? ProviderRefundNo,
|
||||
CommerceRefundStatus Status,
|
||||
string? EventId,
|
||||
JsonElement Payload);
|
||||
|
||||
public sealed record UpdateReconciliationIssueCommand(
|
||||
Guid IssueId,
|
||||
@@ -324,4 +400,72 @@ public interface ICommerceAdminService
|
||||
CommerceAdminActor actor,
|
||||
UpdateReconciliationIssueCommand command,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TenantReconciliationItemList> GetReconciliationItemsAsync(
|
||||
CommerceAdminActor actor,
|
||||
Guid batchId,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TenantReconciliationIssueEventList> GetReconciliationIssueEventsAsync(
|
||||
CommerceAdminActor actor,
|
||||
Guid issueId,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TenantCommerceAnomalySummary> GetAnomalySummaryAsync(
|
||||
CommerceAdminActor actor,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TenantAdjustmentVoucherList> GetAdjustmentVouchersAsync(
|
||||
CommerceAdminActor actor,
|
||||
CommerceAdminQuery query,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<CommerceAdjustmentVoucher> GetAdjustmentVoucherAsync(
|
||||
CommerceAdminActor actor,
|
||||
Guid voucherId,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<CommerceAdjustmentVoucher> CreateAdjustmentVoucherAsync(
|
||||
CommerceAdminActor actor,
|
||||
CreateAdjustmentVoucherCommand command,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<CommerceAdjustmentVoucher> UpdateAdjustmentVoucherStatusAsync(
|
||||
CommerceAdminActor actor,
|
||||
UpdateAdjustmentVoucherStatusCommand command,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TenantAdjustmentVoucherEventList> GetAdjustmentVoucherEventsAsync(
|
||||
CommerceAdminActor actor,
|
||||
Guid voucherId,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TenantAdjustmentReport> GetAdjustmentReportAsync(
|
||||
CommerceAdminActor actor,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<ReconciliationImportPreview> PreviewReconciliationImportAsync(
|
||||
CommerceAdminActor actor,
|
||||
PreviewReconciliationImportCommand command,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<CommerceReconciliationBatch> ImportReconciliationAsync(
|
||||
CommerceAdminActor actor,
|
||||
ImportReconciliationCommand command,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<BackgroundJobItem> RequestProviderBillJobAsync(
|
||||
CommerceAdminActor actor,
|
||||
RequestProviderBillJobCommand command,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<IReadOnlyCollection<BackgroundJobItem>> GetProviderBillJobsAsync(
|
||||
CommerceAdminActor actor,
|
||||
CommerceAdminQuery query,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<CommerceRefundRequest> ProcessRefundNotificationAsync(
|
||||
Guid tenantId,
|
||||
RefundNotificationCommand command,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
262
Tiku.Application/PlatformAdmin/PlatformAdminModels.cs
Normal file
262
Tiku.Application/PlatformAdmin/PlatformAdminModels.cs
Normal file
@@ -0,0 +1,262 @@
|
||||
using System.Text.Json;
|
||||
using Tiku.Domain.Commerce;
|
||||
using Tiku.Domain.Platform;
|
||||
using Tiku.Domain.Tenancy;
|
||||
using Tiku.Domain.Identity;
|
||||
|
||||
namespace Tiku.Application.PlatformAdmin;
|
||||
|
||||
public sealed record PlatformAdminActor(Guid UserId);
|
||||
|
||||
public sealed record PlatformAdminQuery(string? Status = null, string? Search = null, int? Limit = null);
|
||||
|
||||
public sealed record PlatformOverview(
|
||||
int TenantCount,
|
||||
int ActiveTenantCount,
|
||||
int SuspendedTenantCount,
|
||||
int OrderCount,
|
||||
int PaidOrderCount,
|
||||
int RevenueCents,
|
||||
int QuestionBankCount,
|
||||
int QuestionCount,
|
||||
int LearningActiveUserCount);
|
||||
|
||||
public sealed record PlatformTenantList(IReadOnlyCollection<PlatformTenantItem> Items);
|
||||
|
||||
public sealed record PlatformTenantItem(
|
||||
Guid Id,
|
||||
string Slug,
|
||||
string Name,
|
||||
string? LegalName,
|
||||
TenantStatus Status,
|
||||
TenantMode Mode,
|
||||
BillingStatus BillingStatus,
|
||||
DateTimeOffset? SubscriptionExpiresAt,
|
||||
int DomainCount,
|
||||
DateTimeOffset CreatedAt,
|
||||
DateTimeOffset UpdatedAt);
|
||||
|
||||
public sealed record PlatformTenantDetail(
|
||||
PlatformTenantItem Tenant,
|
||||
IReadOnlyCollection<PlatformTenantDomainItem> Domains,
|
||||
IReadOnlyCollection<PlatformTenantSubscriptionItem> Subscriptions,
|
||||
TenantBillingProfileItem? BillingProfile);
|
||||
|
||||
public sealed record PlatformTenantDomainItem(
|
||||
Guid Id,
|
||||
Guid TenantId,
|
||||
string Host,
|
||||
TenantDomainType DomainType,
|
||||
TenantDomainStatus Status,
|
||||
bool IsPrimary,
|
||||
DateTimeOffset? VerifiedAt,
|
||||
DateTimeOffset? DnsVerifiedAt,
|
||||
DateTimeOffset? TlsReadyAt,
|
||||
DateTimeOffset? LastCheckedAt,
|
||||
string? LastFailureReason);
|
||||
|
||||
public sealed record PlatformTenantSubscriptionItem(
|
||||
Guid Id,
|
||||
Guid TenantId,
|
||||
string PlanCode,
|
||||
TenantSubscriptionStatus Status,
|
||||
DateTimeOffset? StartsAt,
|
||||
DateTimeOffset? ExpiresAt,
|
||||
string? BillingCycle,
|
||||
int AmountCents,
|
||||
JsonElement Metadata);
|
||||
|
||||
public sealed record TenantBillingProfileItem(
|
||||
Guid TenantId,
|
||||
string? BillingName,
|
||||
string? TaxId,
|
||||
string? ContactName,
|
||||
string? ContactPhoneMasked,
|
||||
string? ContactEmail,
|
||||
string? BillingAddress,
|
||||
string? InvoiceTitle,
|
||||
TenantInvoiceTitleType? InvoiceType,
|
||||
string? BankName,
|
||||
string? BankAccountMasked,
|
||||
JsonElement Metadata);
|
||||
|
||||
public sealed record CreatePlatformTenantCommand(
|
||||
string Slug,
|
||||
string Name,
|
||||
string? LegalName,
|
||||
TenantStatus Status,
|
||||
BillingStatus BillingStatus,
|
||||
JsonElement Metadata);
|
||||
|
||||
public sealed record UpdatePlatformTenantStatusCommand(
|
||||
Guid TenantId,
|
||||
TenantStatus Status,
|
||||
BillingStatus BillingStatus,
|
||||
string? Reason);
|
||||
|
||||
public sealed record UpsertPlatformTenantBillingProfileCommand(
|
||||
Guid TenantId,
|
||||
string? BillingName,
|
||||
string? TaxId,
|
||||
string? ContactName,
|
||||
string? ContactPhone,
|
||||
string? ContactEmail,
|
||||
string? BillingAddress,
|
||||
string? InvoiceTitle,
|
||||
TenantInvoiceTitleType? InvoiceType,
|
||||
string? BankName,
|
||||
string? BankAccountMasked,
|
||||
JsonElement Metadata);
|
||||
|
||||
public sealed record PlatformPlanList(IReadOnlyCollection<PlatformSaasPlan> Items);
|
||||
|
||||
public sealed record UpsertPlatformSubscriptionCommand(
|
||||
Guid TenantId,
|
||||
string PlanCode,
|
||||
TenantSubscriptionStatus Status,
|
||||
DateTimeOffset? StartsAt,
|
||||
DateTimeOffset? ExpiresAt,
|
||||
string? BillingCycle,
|
||||
int AmountCents,
|
||||
JsonElement Metadata);
|
||||
|
||||
public sealed record PlatformDomainList(IReadOnlyCollection<PlatformTenantDomainItem> Items);
|
||||
|
||||
public sealed record PlatformDomainRecheckResult(Guid DomainId, TenantDomainStatus Status, DateTimeOffset LastCheckedAt);
|
||||
|
||||
public sealed record PlatformStaffList(IReadOnlyCollection<PlatformStaffItem> Items);
|
||||
|
||||
public sealed record PlatformStaffItem(
|
||||
Guid UserId,
|
||||
string? Name,
|
||||
string? PhoneMasked,
|
||||
string? Email,
|
||||
UserStatus Status,
|
||||
IReadOnlyCollection<string> RoleCodes,
|
||||
DateTimeOffset CreatedAt,
|
||||
DateTimeOffset UpdatedAt);
|
||||
|
||||
public sealed record UpsertPlatformStaffCommand(
|
||||
Guid? UserId,
|
||||
string? Email,
|
||||
string? Phone,
|
||||
string? Name,
|
||||
UserStatus Status,
|
||||
IReadOnlyCollection<Guid> RoleIds);
|
||||
|
||||
public sealed record UpdatePlatformStaffStatusCommand(Guid UserId, UserStatus Status, string? Reason);
|
||||
|
||||
public sealed record PlatformAuditLogList(IReadOnlyCollection<PlatformAuditLogItem> Items);
|
||||
|
||||
public sealed record PlatformAuditLogItem(
|
||||
Guid Id,
|
||||
Guid? TenantId,
|
||||
Guid? ActorUserId,
|
||||
string Action,
|
||||
string? TargetType,
|
||||
string? TargetId,
|
||||
JsonElement Details,
|
||||
string? IpAddress,
|
||||
string? UserAgent,
|
||||
DateTimeOffset CreatedAt);
|
||||
|
||||
public sealed record PlatformAuditAlertList(IReadOnlyCollection<PlatformAuditAlert> Items);
|
||||
|
||||
public sealed record UpdatePlatformAuditAlertStatusCommand(
|
||||
Guid AlertId,
|
||||
PlatformAuditAlertStatus Status,
|
||||
string? ResolutionNote);
|
||||
|
||||
public sealed record PlatformDunningChannelList(IReadOnlyCollection<PlatformDunningChannelItem> Items);
|
||||
|
||||
public sealed record PlatformDunningChannelItem(
|
||||
Guid Id,
|
||||
string ChannelCode,
|
||||
string Name,
|
||||
string? Description,
|
||||
bool Enabled,
|
||||
PlatformDunningProvider Provider,
|
||||
string WebhookUrlMasked,
|
||||
string? SecretRef,
|
||||
IReadOnlyCollection<string> ReminderTypes,
|
||||
IReadOnlyCollection<string> ReminderChannels,
|
||||
int MinReminderLevel,
|
||||
IReadOnlyCollection<Guid> TenantIds,
|
||||
int TimeoutSeconds,
|
||||
JsonElement Metadata,
|
||||
DateTimeOffset CreatedAt,
|
||||
DateTimeOffset UpdatedAt);
|
||||
|
||||
public sealed record UpsertPlatformDunningChannelCommand(
|
||||
Guid? ChannelId,
|
||||
string ChannelCode,
|
||||
string Name,
|
||||
string? Description,
|
||||
bool Enabled,
|
||||
PlatformDunningProvider Provider,
|
||||
string WebhookUrl,
|
||||
string? SecretRef,
|
||||
IReadOnlyCollection<string> ReminderTypes,
|
||||
IReadOnlyCollection<string> ReminderChannels,
|
||||
int MinReminderLevel,
|
||||
IReadOnlyCollection<Guid> TenantIds,
|
||||
int TimeoutSeconds,
|
||||
JsonElement Metadata);
|
||||
|
||||
public sealed record DisablePlatformDunningChannelCommand(Guid ChannelId, string? Reason);
|
||||
|
||||
public sealed record PlatformDunningEventList(IReadOnlyCollection<PlatformDunningEventItem> Items);
|
||||
|
||||
public sealed record PlatformDunningEventItem(
|
||||
Guid Id,
|
||||
Guid TenantId,
|
||||
Guid ChannelId,
|
||||
Guid ReminderId,
|
||||
Guid InvoiceId,
|
||||
PlatformDunningProvider Provider,
|
||||
PlatformDunningNotificationStatus Status,
|
||||
int Attempts,
|
||||
DateTimeOffset ScheduledAt,
|
||||
DateTimeOffset? NextAttemptAt,
|
||||
DateTimeOffset? LastAttemptAt,
|
||||
DateTimeOffset? SentAt,
|
||||
string? LastError,
|
||||
int? LastHttpCode,
|
||||
string? LastResponseSummary,
|
||||
JsonElement RequestPayload,
|
||||
JsonElement Metadata,
|
||||
DateTimeOffset CreatedAt,
|
||||
DateTimeOffset UpdatedAt);
|
||||
|
||||
public sealed record RetryPlatformDunningEventCommand(Guid EventId, string? Reason);
|
||||
|
||||
public interface IPlatformAdminService
|
||||
{
|
||||
Task<PlatformOverview> GetOverviewAsync(PlatformAdminActor actor, CancellationToken cancellationToken = default);
|
||||
Task<PlatformTenantList> GetTenantsAsync(PlatformAdminActor actor, PlatformAdminQuery query, CancellationToken cancellationToken = default);
|
||||
Task<PlatformTenantDetail> GetTenantDetailAsync(PlatformAdminActor actor, Guid tenantId, CancellationToken cancellationToken = default);
|
||||
Task<PlatformTenantItem> CreateTenantAsync(PlatformAdminActor actor, CreatePlatformTenantCommand command, CancellationToken cancellationToken = default);
|
||||
Task<PlatformTenantItem> UpdateTenantStatusAsync(PlatformAdminActor actor, UpdatePlatformTenantStatusCommand command, CancellationToken cancellationToken = default);
|
||||
Task<TenantBillingProfileItem> UpsertTenantBillingProfileAsync(PlatformAdminActor actor, UpsertPlatformTenantBillingProfileCommand command, CancellationToken cancellationToken = default);
|
||||
Task<PlatformPlanList> GetPlansAsync(PlatformAdminActor actor, PlatformAdminQuery query, CancellationToken cancellationToken = default);
|
||||
Task<PlatformTenantSubscriptionItem> UpsertSubscriptionAsync(PlatformAdminActor actor, UpsertPlatformSubscriptionCommand command, CancellationToken cancellationToken = default);
|
||||
Task<PlatformDomainList> GetDomainsAsync(PlatformAdminActor actor, PlatformAdminQuery query, CancellationToken cancellationToken = default);
|
||||
Task<PlatformDomainRecheckResult> RecheckDomainAsync(PlatformAdminActor actor, Guid domainId, CancellationToken cancellationToken = default);
|
||||
Task<PlatformStaffList> GetStaffAsync(PlatformAdminActor actor, PlatformAdminQuery query, CancellationToken cancellationToken = default);
|
||||
Task<PlatformStaffItem> UpsertStaffAsync(PlatformAdminActor actor, UpsertPlatformStaffCommand command, CancellationToken cancellationToken = default);
|
||||
Task<PlatformStaffItem> UpdateStaffStatusAsync(PlatformAdminActor actor, UpdatePlatformStaffStatusCommand command, CancellationToken cancellationToken = default);
|
||||
Task<PlatformAuditLogList> GetAuditLogsAsync(PlatformAdminActor actor, PlatformAdminQuery query, CancellationToken cancellationToken = default);
|
||||
Task<PlatformAuditAlertList> GetAuditAlertsAsync(PlatformAdminActor actor, PlatformAdminQuery query, CancellationToken cancellationToken = default);
|
||||
Task<PlatformAuditAlert> UpdateAuditAlertStatusAsync(PlatformAdminActor actor, UpdatePlatformAuditAlertStatusCommand command, CancellationToken cancellationToken = default);
|
||||
Task<PlatformDunningChannelList> GetDunningChannelsAsync(PlatformAdminActor actor, PlatformAdminQuery query, CancellationToken cancellationToken = default);
|
||||
Task<PlatformDunningChannelItem> UpsertDunningChannelAsync(PlatformAdminActor actor, UpsertPlatformDunningChannelCommand command, CancellationToken cancellationToken = default);
|
||||
Task<PlatformDunningChannelItem> DisableDunningChannelAsync(PlatformAdminActor actor, DisablePlatformDunningChannelCommand command, CancellationToken cancellationToken = default);
|
||||
Task<PlatformDunningEventList> GetDunningEventsAsync(PlatformAdminActor actor, PlatformAdminQuery query, CancellationToken cancellationToken = default);
|
||||
Task<PlatformDunningEventItem> GetDunningEventDetailAsync(PlatformAdminActor actor, Guid eventId, CancellationToken cancellationToken = default);
|
||||
Task<PlatformDunningEventItem> RetryDunningEventAsync(PlatformAdminActor actor, RetryPlatformDunningEventCommand command, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public sealed class PlatformAdminException(string message, string code) : Exception(message)
|
||||
{
|
||||
public string Code { get; } = code;
|
||||
}
|
||||
@@ -20,6 +20,7 @@ public static class BackendPermissions
|
||||
public const string PlatformRoleManage = "platform:role:manage";
|
||||
public const string PlatformQuestionBankManage = "platform:question-bank:manage";
|
||||
public const string PlatformAuditView = "platform:audit:view";
|
||||
public const string PlatformBillingNotification = "platform:billing:notification";
|
||||
|
||||
public static readonly IReadOnlySet<string> Tenant = new HashSet<string>(StringComparer.Ordinal)
|
||||
{
|
||||
@@ -43,7 +44,8 @@ public static class BackendPermissions
|
||||
PlatformStaffManage,
|
||||
PlatformRoleManage,
|
||||
PlatformQuestionBankManage,
|
||||
PlatformAuditView
|
||||
PlatformAuditView,
|
||||
PlatformBillingNotification
|
||||
};
|
||||
|
||||
public static void EnsureTenant(string permissionCode)
|
||||
|
||||
@@ -5,6 +5,10 @@ namespace Tiku.Application.TenantAdmin;
|
||||
|
||||
public interface ITenantAdminDirectService
|
||||
{
|
||||
Task<TenantAdminOverviewItem> GetOverviewAsync(
|
||||
TenantAdminActor actor,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TenantAdminClassList> GetClassesAsync(
|
||||
TenantAdminActor actor,
|
||||
TenantAdminClassFilter filter,
|
||||
@@ -50,6 +54,56 @@ public interface ITenantAdminDirectService
|
||||
UpdateTenantAdminStudentStatusCommand command,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TenantAdminStudentImportPreview> PreviewStudentImportAsync(
|
||||
TenantAdminActor actor,
|
||||
TenantAdminStudentImportCommand command,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TenantAdminStudentImportResult> ImportStudentsAsync(
|
||||
TenantAdminActor actor,
|
||||
TenantAdminStudentImportCommand command,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TenantAdminBulkOperationResult> BulkAssignClassAsync(
|
||||
TenantAdminActor actor,
|
||||
TenantAdminBulkAssignClassCommand command,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TenantAdminBulkOperationResult> BulkUpdateStudentStatusAsync(
|
||||
TenantAdminActor actor,
|
||||
TenantAdminBulkStatusCommand command,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<CatalogList<TenantSupervisionRuleItem>> GetSupervisionRulesAsync(
|
||||
TenantAdminActor actor,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<ContentManagementResult<TenantSupervisionRuleItem>> UpsertSupervisionRuleAsync(
|
||||
TenantAdminActor actor,
|
||||
UpsertTenantSupervisionRuleCommand command,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TenantSupervisionPreview> PreviewSupervisionAsync(
|
||||
TenantAdminActor actor,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TenantSupervisionGenerateResult> GenerateSupervisionFollowupsAsync(
|
||||
TenantAdminActor actor,
|
||||
TenantSupervisionGenerateCommand command,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TenantFollowupReport> GetFollowupReportAsync(
|
||||
TenantAdminActor actor,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TenantFeedbackReport> GetFeedbackReportAsync(
|
||||
TenantAdminActor actor,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TenantPointRiskReport> GetPointRiskReportAsync(
|
||||
TenantAdminActor actor,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<CatalogList<TenantAdminStudentNoteItem>> GetStudentNotesAsync(
|
||||
TenantAdminActor actor,
|
||||
TenantAdminStudentActivityFilter filter,
|
||||
|
||||
@@ -78,6 +78,20 @@ public sealed record TenantAdminFeedbackFilter(
|
||||
string? Keyword = null,
|
||||
int? Limit = null);
|
||||
|
||||
public sealed record TenantAdminOverviewItem(
|
||||
int StudentCount,
|
||||
int ClassCount,
|
||||
int StaffCount,
|
||||
int ActivePracticeCount,
|
||||
int TodayPracticeCount,
|
||||
int PendingFollowupCount,
|
||||
int UnreadNotificationCount,
|
||||
int PaidOrderCount,
|
||||
int RevenueCents,
|
||||
int PendingRefundCount,
|
||||
int OpenReconciliationIssueCount,
|
||||
DateTimeOffset GeneratedAt);
|
||||
|
||||
public sealed record UpsertTenantAdminClassCommand(
|
||||
Guid? Id,
|
||||
Guid? RegionId,
|
||||
@@ -120,6 +134,109 @@ public sealed record UpdateTenantAdminStudentStatusCommand(
|
||||
string? Status,
|
||||
string? Reason);
|
||||
|
||||
public sealed record TenantAdminStudentImportRowCommand(
|
||||
UserLookupCommand User,
|
||||
Guid? RegionId,
|
||||
Guid? ClassId,
|
||||
string? AvatarPreset,
|
||||
JsonElement RawProfile);
|
||||
|
||||
public sealed record TenantAdminStudentImportCommand(
|
||||
IReadOnlyCollection<TenantAdminStudentImportRowCommand> Rows);
|
||||
|
||||
public sealed record TenantAdminStudentImportPreview(
|
||||
int TotalCount,
|
||||
int ValidCount,
|
||||
int InvalidCount,
|
||||
IReadOnlyCollection<TenantAdminStudentImportPreviewItem> Items);
|
||||
|
||||
public sealed record TenantAdminStudentImportPreviewItem(
|
||||
int RowNo,
|
||||
bool Valid,
|
||||
string? Reason,
|
||||
string? Phone,
|
||||
string? Email,
|
||||
string? Name,
|
||||
Guid? RegionId,
|
||||
Guid? ClassId);
|
||||
|
||||
public sealed record TenantAdminStudentImportResult(
|
||||
int TotalCount,
|
||||
int CreatedOrUpdatedCount,
|
||||
int ClassAssignedCount,
|
||||
IReadOnlyCollection<TenantAdminStudentImportPreviewItem> InvalidItems);
|
||||
|
||||
public sealed record TenantAdminBulkAssignClassCommand(
|
||||
Guid ClassId,
|
||||
IReadOnlyCollection<Guid> UserIds);
|
||||
|
||||
public sealed record TenantAdminBulkStatusCommand(
|
||||
IReadOnlyCollection<Guid> UserIds,
|
||||
string? Status,
|
||||
string? Reason);
|
||||
|
||||
public sealed record TenantAdminBulkOperationResult(
|
||||
int RequestedCount,
|
||||
int SucceededCount,
|
||||
int FailedCount,
|
||||
IReadOnlyCollection<Guid> FailedUserIds);
|
||||
|
||||
public sealed record TenantSupervisionRuleItem(
|
||||
string Code,
|
||||
string Title,
|
||||
bool Enabled,
|
||||
int? DaysWithoutCheckIn,
|
||||
int? MaxQuestionsAnsweredToday,
|
||||
string FollowupType,
|
||||
string Priority,
|
||||
JsonElement Metadata);
|
||||
|
||||
public sealed record UpsertTenantSupervisionRuleCommand(
|
||||
string Code,
|
||||
string Title,
|
||||
bool Enabled,
|
||||
int? DaysWithoutCheckIn,
|
||||
int? MaxQuestionsAnsweredToday,
|
||||
string? FollowupType,
|
||||
string? Priority,
|
||||
JsonElement Metadata);
|
||||
|
||||
public sealed record TenantSupervisionPreview(
|
||||
IReadOnlyCollection<TenantSupervisionRiskStudentItem> Items);
|
||||
|
||||
public sealed record TenantSupervisionRiskStudentItem(
|
||||
Guid UserId,
|
||||
string? Name,
|
||||
string? PhoneMasked,
|
||||
Guid? RegionId,
|
||||
IReadOnlyCollection<string> RuleCodes,
|
||||
IReadOnlyCollection<string> Reasons);
|
||||
|
||||
public sealed record TenantSupervisionGenerateCommand(
|
||||
IReadOnlyCollection<Guid>? UserIds,
|
||||
Guid? AssignedToUserId,
|
||||
DateTimeOffset? DueAt);
|
||||
|
||||
public sealed record TenantSupervisionGenerateResult(int CreatedCount);
|
||||
|
||||
public sealed record TenantFollowupReport(
|
||||
int OpenCount,
|
||||
int InProgressCount,
|
||||
int DoneCount,
|
||||
int OverdueCount);
|
||||
|
||||
public sealed record TenantFeedbackReport(
|
||||
int PendingCount,
|
||||
int AcceptedCount,
|
||||
int RejectedCount,
|
||||
int ResolvedCount,
|
||||
int ClosedCount);
|
||||
|
||||
public sealed record TenantPointRiskReport(
|
||||
int NegativeScoreUserCount,
|
||||
int HighPointClaimUserCount,
|
||||
int CancelledExchangeOrderCount);
|
||||
|
||||
public sealed record UpsertTenantAdminStudentNoteCommand(
|
||||
Guid? Id,
|
||||
Guid StudentUserId,
|
||||
|
||||
Reference in New Issue
Block a user