feat: add tenant admin direct operations endpoints

This commit is contained in:
xiong
2026-07-26 18:53:01 +08:00
parent 89e1f2a4df
commit f671a7f07a
8 changed files with 1822 additions and 0 deletions

View File

@@ -0,0 +1,72 @@
using Tiku.Application.Catalog;
using Tiku.Application.Content;
namespace Tiku.Application.TenantAdmin;
public interface ITenantAdminDirectService
{
Task<TenantAdminClassList> GetClassesAsync(
TenantAdminActor actor,
TenantAdminClassFilter filter,
CancellationToken cancellationToken = default);
Task<ContentManagementResult<TenantAdminClassItem>> UpsertClassAsync(
TenantAdminActor actor,
UpsertTenantAdminClassCommand command,
CancellationToken cancellationToken = default);
Task<ContentManagementResult<TenantAdminClassItem>> DisableClassAsync(
TenantAdminActor actor,
Guid classId,
CancellationToken cancellationToken = default);
Task<CatalogList<TenantAdminClassMemberItem>> GetClassMembersAsync(
TenantAdminActor actor,
TenantAdminClassMemberFilter filter,
CancellationToken cancellationToken = default);
Task<ContentManagementResult<TenantAdminClassMemberItem>> UpsertClassMemberAsync(
TenantAdminActor actor,
UpsertTenantAdminClassMemberCommand command,
CancellationToken cancellationToken = default);
Task<ContentManagementResult<TenantAdminClassMemberItem>> RemoveClassMemberAsync(
TenantAdminActor actor,
Guid classMemberId,
CancellationToken cancellationToken = default);
Task<TenantAdminStudentList> GetStudentsAsync(
TenantAdminActor actor,
TenantAdminStudentFilter filter,
CancellationToken cancellationToken = default);
Task<ContentManagementResult<TenantAdminStudentItem>> UpsertStudentAsync(
TenantAdminActor actor,
UpsertTenantAdminStudentCommand command,
CancellationToken cancellationToken = default);
Task<ContentManagementResult<TenantAdminStudentStatusItem>> UpdateStudentStatusAsync(
TenantAdminActor actor,
UpdateTenantAdminStudentStatusCommand command,
CancellationToken cancellationToken = default);
Task<CatalogList<TenantAdminStudentNoteItem>> GetStudentNotesAsync(
TenantAdminActor actor,
TenantAdminStudentActivityFilter filter,
CancellationToken cancellationToken = default);
Task<ContentManagementResult<TenantAdminStudentNoteItem>> UpsertStudentNoteAsync(
TenantAdminActor actor,
UpsertTenantAdminStudentNoteCommand command,
CancellationToken cancellationToken = default);
Task<CatalogList<TenantAdminStudentFollowupItem>> GetStudentFollowupsAsync(
TenantAdminActor actor,
TenantAdminStudentActivityFilter filter,
CancellationToken cancellationToken = default);
Task<ContentManagementResult<TenantAdminStudentFollowupItem>> UpsertStudentFollowupAsync(
TenantAdminActor actor,
UpsertTenantAdminStudentFollowupCommand command,
CancellationToken cancellationToken = default);
}

View File

@@ -0,0 +1,210 @@
using System.Text.Json;
using Tiku.Domain.Common;
using Tiku.Domain.Tenancy;
namespace Tiku.Application.TenantAdmin;
public sealed record TenantAdminActor(Guid TenantId, Guid UserId);
public sealed record TenantAdminClassFilter(
Guid? RegionId = null,
string? Status = null,
string? Keyword = null,
int? Limit = null);
public sealed record TenantAdminClassMemberFilter(
Guid ClassId,
string? MemberType = null,
string? Status = null,
int? Limit = null);
public sealed record TenantAdminStudentFilter(
Guid? RegionId = null,
Guid? ClassId = null,
string? Status = null,
string? Keyword = null,
int? Limit = null);
public sealed record TenantAdminStudentActivityFilter(
Guid? StudentUserId = null,
string? Status = null,
int? Limit = null);
public sealed record UpsertTenantAdminClassCommand(
Guid? Id,
Guid? RegionId,
string? LegacyId,
string? Code,
string Name,
string? Description,
string? Status,
int? Order,
JsonElement Metadata);
public sealed record UserLookupCommand(
Guid? UserId,
string? Username,
string? Email,
string? Phone,
string? Name,
string? AvatarUrl);
public sealed record UpsertTenantAdminClassMemberCommand(
Guid ClassId,
UserLookupCommand User,
string? MemberType,
string? Status,
JsonElement Metadata);
public sealed record UpsertTenantAdminStudentCommand(
UserLookupCommand User,
Guid? RegionId,
Guid? SelectedSchoolId,
Guid? SelectedMajorId,
string? AvatarPreset,
JsonElement Stats,
JsonElement Progress,
JsonElement ModuleSelections,
JsonElement RawProfile);
public sealed record UpdateTenantAdminStudentStatusCommand(
Guid UserId,
string? Status,
string? Reason);
public sealed record UpsertTenantAdminStudentNoteCommand(
Guid? Id,
Guid StudentUserId,
string? NoteType,
string Content,
string? Visibility,
bool? IsPinned,
JsonElement Metadata);
public sealed record UpsertTenantAdminStudentFollowupCommand(
Guid? Id,
Guid StudentUserId,
Guid? AssignedToUserId,
Guid? ClassId,
string Title,
string? Description,
string? FollowupType,
string? Priority,
string? Status,
DateTimeOffset? DueAt,
JsonElement Metadata);
public sealed record TenantAdminClassList(
IReadOnlyCollection<TenantAdminClassItem> Items,
bool Scoped);
public sealed record TenantAdminStudentList(
IReadOnlyCollection<TenantAdminStudentItem> Items,
bool Scoped);
public sealed record TenantAdminClassItem(
Guid Id,
Guid? RegionId,
string? RegionName,
string? LegacyId,
string? Code,
string Name,
string? Description,
TenantRecordStatus Status,
int Order,
JsonElement Metadata,
int StudentCount,
int StaffCount,
DateTimeOffset CreatedAt,
DateTimeOffset UpdatedAt);
public sealed record TenantAdminClassMemberItem(
Guid Id,
Guid ClassId,
Guid UserId,
TenantClassMemberType MemberType,
TenantClassMemberStatus Status,
DateTimeOffset JoinedAt,
DateTimeOffset? LeftAt,
JsonElement Metadata,
TenantAdminUserSummary User);
public sealed record TenantAdminUserSummary(
Guid Id,
string? Username,
string? Email,
string? Phone,
string? Name,
string? AvatarUrl,
string PrimaryRole);
public sealed record TenantAdminStudentItem(
Guid MembershipId,
Guid UserId,
MembershipStatus Status,
TenantAdminUserSummary User,
Guid? ProfileId,
string AvatarPreset,
Guid? RegionId,
string? RegionName,
Guid? SelectedSchoolId,
string? SelectedSchoolName,
Guid? SelectedMajorId,
string? SelectedMajorName,
JsonElement Stats,
JsonElement Progress,
JsonElement ModuleSelections,
IReadOnlyCollection<TenantAdminStudentClassSummary> Classes,
DateTimeOffset CreatedAt,
DateTimeOffset UpdatedAt);
public sealed record TenantAdminStudentClassSummary(
Guid ClassId,
string ClassName,
string? ClassCode,
TenantClassMemberType MemberType,
DateTimeOffset JoinedAt);
public sealed record TenantAdminStudentStatusItem(
Guid MembershipId,
Guid UserId,
TenantRole Role,
MembershipStatus Status,
DateTimeOffset UpdatedAt);
public sealed record TenantAdminStudentNoteItem(
Guid Id,
Guid StudentUserId,
StudentNoteType NoteType,
string Content,
StudentNoteVisibility Visibility,
bool IsPinned,
JsonElement Metadata,
Guid? CreatedBy,
Guid? UpdatedBy,
DateTimeOffset CreatedAt,
DateTimeOffset UpdatedAt);
public sealed record TenantAdminStudentFollowupItem(
Guid Id,
Guid StudentUserId,
Guid? AssignedToUserId,
Guid? ClassId,
string Title,
string? Description,
StudentFollowupType FollowupType,
StudentFollowupPriority Priority,
StudentFollowupStatus Status,
DateTimeOffset? DueAt,
DateTimeOffset? CompletedAt,
Guid? CompletedBy,
JsonElement Metadata,
Guid? CreatedBy,
Guid? UpdatedBy,
DateTimeOffset CreatedAt,
DateTimeOffset UpdatedAt);
public sealed class TenantAdminDirectException(string message, string code) : Exception(message)
{
public string Code { get; } = code;
}