forked from gongxuegit/tiku-backend.net
feat: complete phase six backoffice operations
This commit is contained in:
263
Tiku.Api/Contracts/PlatformAdminDtos.cs
Normal file
263
Tiku.Api/Contracts/PlatformAdminDtos.cs
Normal file
@@ -0,0 +1,263 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json;
|
||||
using Tiku.Application.PlatformAdmin;
|
||||
using Tiku.Domain.Common;
|
||||
using Tiku.Domain.Commerce;
|
||||
using Tiku.Domain.Identity;
|
||||
using Tiku.Domain.Platform;
|
||||
using Tiku.Domain.Tenancy;
|
||||
|
||||
namespace Tiku.Api.Contracts;
|
||||
|
||||
public sealed class PlatformAdminQueryDto
|
||||
{
|
||||
[StringLength(32)]
|
||||
public string? Status { get; set; }
|
||||
|
||||
[StringLength(200)]
|
||||
public string? Search { get; set; }
|
||||
|
||||
[Range(1, 200)]
|
||||
public int? Limit { get; set; }
|
||||
|
||||
public PlatformAdminQuery ToQuery() => new(Status, Search, Limit);
|
||||
}
|
||||
|
||||
public sealed class CreatePlatformTenantDto
|
||||
{
|
||||
[Required]
|
||||
[StringLength(100)]
|
||||
public string Slug { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
[StringLength(200)]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(300)]
|
||||
public string? LegalName { get; set; }
|
||||
|
||||
public TenantStatus Status { get; set; } = TenantStatus.Active;
|
||||
public BillingStatus BillingStatus { get; set; } = BillingStatus.Trial;
|
||||
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
|
||||
|
||||
public CreatePlatformTenantCommand ToCommand() => new(Slug, Name, LegalName, Status, BillingStatus, Metadata);
|
||||
}
|
||||
|
||||
public sealed class UpdatePlatformTenantStatusDto
|
||||
{
|
||||
[Required]
|
||||
public Guid TenantId { get; set; }
|
||||
|
||||
public TenantStatus Status { get; set; } = TenantStatus.Active;
|
||||
public BillingStatus BillingStatus { get; set; } = BillingStatus.Active;
|
||||
|
||||
[StringLength(1000)]
|
||||
public string? Reason { get; set; }
|
||||
|
||||
public UpdatePlatformTenantStatusCommand ToCommand() => new(TenantId, Status, BillingStatus, Reason);
|
||||
}
|
||||
|
||||
public sealed class UpsertPlatformTenantBillingProfileDto
|
||||
{
|
||||
[Required]
|
||||
public Guid TenantId { get; set; }
|
||||
|
||||
[StringLength(300)]
|
||||
public string? BillingName { get; set; }
|
||||
|
||||
[StringLength(100)]
|
||||
public string? TaxId { get; set; }
|
||||
|
||||
[StringLength(100)]
|
||||
public string? ContactName { get; set; }
|
||||
|
||||
[StringLength(32)]
|
||||
public string? ContactPhone { get; set; }
|
||||
|
||||
[StringLength(320)]
|
||||
public string? ContactEmail { get; set; }
|
||||
|
||||
[StringLength(1000)]
|
||||
public string? BillingAddress { get; set; }
|
||||
|
||||
[StringLength(300)]
|
||||
public string? InvoiceTitle { get; set; }
|
||||
|
||||
public TenantInvoiceTitleType? InvoiceType { get; set; }
|
||||
|
||||
[StringLength(300)]
|
||||
public string? BankName { get; set; }
|
||||
|
||||
[StringLength(100)]
|
||||
public string? BankAccountMasked { get; set; }
|
||||
|
||||
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
|
||||
|
||||
public UpsertPlatformTenantBillingProfileCommand ToCommand() => new(
|
||||
TenantId,
|
||||
BillingName,
|
||||
TaxId,
|
||||
ContactName,
|
||||
ContactPhone,
|
||||
ContactEmail,
|
||||
BillingAddress,
|
||||
InvoiceTitle,
|
||||
InvoiceType,
|
||||
BankName,
|
||||
BankAccountMasked,
|
||||
Metadata);
|
||||
}
|
||||
|
||||
public sealed class UpsertPlatformSubscriptionDto
|
||||
{
|
||||
[Required]
|
||||
public Guid TenantId { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(100)]
|
||||
public string PlanCode { get; set; } = string.Empty;
|
||||
|
||||
public TenantSubscriptionStatus Status { get; set; } = TenantSubscriptionStatus.Active;
|
||||
public DateTimeOffset? StartsAt { get; set; }
|
||||
public DateTimeOffset? ExpiresAt { get; set; }
|
||||
|
||||
[StringLength(32)]
|
||||
public string? BillingCycle { get; set; }
|
||||
|
||||
[Range(0, int.MaxValue)]
|
||||
public int AmountCents { get; set; }
|
||||
|
||||
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
|
||||
|
||||
public UpsertPlatformSubscriptionCommand ToCommand() => new(
|
||||
TenantId,
|
||||
PlanCode,
|
||||
Status,
|
||||
StartsAt,
|
||||
ExpiresAt,
|
||||
BillingCycle,
|
||||
AmountCents,
|
||||
Metadata);
|
||||
}
|
||||
|
||||
public sealed class UpsertPlatformStaffDto
|
||||
{
|
||||
public Guid? UserId { get; set; }
|
||||
|
||||
[StringLength(320)]
|
||||
public string? Email { get; set; }
|
||||
|
||||
[StringLength(32)]
|
||||
public string? Phone { get; set; }
|
||||
|
||||
[StringLength(200)]
|
||||
public string? Name { get; set; }
|
||||
|
||||
public UserStatus Status { get; set; } = UserStatus.Active;
|
||||
public IReadOnlyCollection<Guid> RoleIds { get; set; } = [];
|
||||
|
||||
public UpsertPlatformStaffCommand ToCommand() => new(UserId, Email, Phone, Name, Status, RoleIds);
|
||||
}
|
||||
|
||||
public sealed class UpdatePlatformStaffStatusDto
|
||||
{
|
||||
[Required]
|
||||
public Guid UserId { get; set; }
|
||||
|
||||
public UserStatus Status { get; set; } = UserStatus.Active;
|
||||
|
||||
[StringLength(1000)]
|
||||
public string? Reason { get; set; }
|
||||
|
||||
public UpdatePlatformStaffStatusCommand ToCommand() => new(UserId, Status, Reason);
|
||||
}
|
||||
|
||||
public sealed class UpdatePlatformAuditAlertStatusDto
|
||||
{
|
||||
[Required]
|
||||
public Guid AlertId { get; set; }
|
||||
|
||||
public PlatformAuditAlertStatus Status { get; set; } = PlatformAuditAlertStatus.Acknowledged;
|
||||
|
||||
[StringLength(1000)]
|
||||
public string? ResolutionNote { get; set; }
|
||||
|
||||
public UpdatePlatformAuditAlertStatusCommand ToCommand() => new(AlertId, Status, ResolutionNote);
|
||||
}
|
||||
|
||||
public sealed class UpsertPlatformDunningChannelDto
|
||||
{
|
||||
public Guid? ChannelId { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(100)]
|
||||
public string ChannelCode { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
[StringLength(200)]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(1000)]
|
||||
public string? Description { get; set; }
|
||||
|
||||
public bool Enabled { get; set; } = true;
|
||||
public PlatformDunningProvider Provider { get; set; } = PlatformDunningProvider.Generic;
|
||||
|
||||
[Required]
|
||||
[StringLength(2048)]
|
||||
public string WebhookUrl { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(300)]
|
||||
public string? SecretRef { get; set; }
|
||||
|
||||
public IReadOnlyCollection<string> ReminderTypes { get; set; } = ["overdue", "final_notice"];
|
||||
public IReadOnlyCollection<string> ReminderChannels { get; set; } = ["internal"];
|
||||
|
||||
[Range(1, 20)]
|
||||
public int MinReminderLevel { get; set; } = 1;
|
||||
|
||||
public IReadOnlyCollection<Guid> TenantIds { get; set; } = [];
|
||||
|
||||
[Range(1, 60)]
|
||||
public int TimeoutSeconds { get; set; } = 10;
|
||||
|
||||
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
|
||||
|
||||
public UpsertPlatformDunningChannelCommand ToCommand() => new(
|
||||
ChannelId,
|
||||
ChannelCode,
|
||||
Name,
|
||||
Description,
|
||||
Enabled,
|
||||
Provider,
|
||||
WebhookUrl,
|
||||
SecretRef,
|
||||
ReminderTypes,
|
||||
ReminderChannels,
|
||||
MinReminderLevel,
|
||||
TenantIds,
|
||||
TimeoutSeconds,
|
||||
Metadata);
|
||||
}
|
||||
|
||||
public sealed class DisablePlatformDunningChannelDto
|
||||
{
|
||||
[Required]
|
||||
public Guid ChannelId { get; set; }
|
||||
|
||||
[StringLength(1000)]
|
||||
public string? Reason { get; set; }
|
||||
|
||||
public DisablePlatformDunningChannelCommand ToCommand() => new(ChannelId, Reason);
|
||||
}
|
||||
|
||||
public sealed class RetryPlatformDunningEventDto
|
||||
{
|
||||
[Required]
|
||||
public Guid EventId { get; set; }
|
||||
|
||||
[StringLength(1000)]
|
||||
public string? Reason { get; set; }
|
||||
|
||||
public RetryPlatformDunningEventCommand ToCommand() => new(EventId, Reason);
|
||||
}
|
||||
@@ -252,6 +252,113 @@ public sealed class UpdateTenantAdminStudentStatusDto
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TenantAdminStudentImportRowDto
|
||||
{
|
||||
public TenantAdminUserLookupDto User { get; set; } = new();
|
||||
public Guid? RegionId { get; set; }
|
||||
public Guid? ClassId { get; set; }
|
||||
public string? AvatarPreset { get; set; }
|
||||
public JsonElement RawProfile { get; set; } = JsonDefaults.Object();
|
||||
|
||||
public TenantAdminStudentImportRowCommand ToCommand()
|
||||
{
|
||||
return new TenantAdminStudentImportRowCommand(User.ToCommand(), RegionId, ClassId, AvatarPreset, RawProfile);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TenantAdminStudentImportDto
|
||||
{
|
||||
[Required]
|
||||
public IReadOnlyCollection<TenantAdminStudentImportRowDto> Rows { get; set; } = [];
|
||||
|
||||
public TenantAdminStudentImportCommand ToCommand()
|
||||
{
|
||||
return new TenantAdminStudentImportCommand(Rows.Select(row => row.ToCommand()).ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TenantAdminBulkAssignClassDto
|
||||
{
|
||||
[Required]
|
||||
public Guid ClassId { get; set; }
|
||||
|
||||
[Required]
|
||||
public IReadOnlyCollection<Guid> UserIds { get; set; } = [];
|
||||
|
||||
public TenantAdminBulkAssignClassCommand ToCommand()
|
||||
{
|
||||
return new TenantAdminBulkAssignClassCommand(ClassId, UserIds);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TenantAdminBulkStatusDto
|
||||
{
|
||||
[Required]
|
||||
public IReadOnlyCollection<Guid> UserIds { get; set; } = [];
|
||||
|
||||
public string? Status { get; set; }
|
||||
|
||||
[StringLength(1000)]
|
||||
public string? Reason { get; set; }
|
||||
|
||||
public TenantAdminBulkStatusCommand ToCommand()
|
||||
{
|
||||
return new TenantAdminBulkStatusCommand(UserIds, Status, Reason);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class UpsertTenantSupervisionRuleDto
|
||||
{
|
||||
[Required]
|
||||
[StringLength(100)]
|
||||
public string Code { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
[StringLength(200)]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
[Range(0, 3650)]
|
||||
public int? DaysWithoutCheckIn { get; set; }
|
||||
|
||||
[Range(0, int.MaxValue)]
|
||||
public int? MaxQuestionsAnsweredToday { get; set; }
|
||||
|
||||
[StringLength(50)]
|
||||
public string? FollowupType { get; set; }
|
||||
|
||||
[StringLength(50)]
|
||||
public string? Priority { get; set; }
|
||||
|
||||
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
|
||||
|
||||
public UpsertTenantSupervisionRuleCommand ToCommand()
|
||||
{
|
||||
return new UpsertTenantSupervisionRuleCommand(
|
||||
Code,
|
||||
Title,
|
||||
Enabled,
|
||||
DaysWithoutCheckIn,
|
||||
MaxQuestionsAnsweredToday,
|
||||
FollowupType,
|
||||
Priority,
|
||||
Metadata);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TenantSupervisionGenerateDto
|
||||
{
|
||||
public IReadOnlyCollection<Guid>? UserIds { get; set; }
|
||||
public Guid? AssignedToUserId { get; set; }
|
||||
public DateTimeOffset? DueAt { get; set; }
|
||||
|
||||
public TenantSupervisionGenerateCommand ToCommand()
|
||||
{
|
||||
return new TenantSupervisionGenerateCommand(UserIds, AssignedToUserId, DueAt);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class UpsertTenantAdminStudentNoteDto
|
||||
{
|
||||
public Guid? Id { get; set; }
|
||||
|
||||
@@ -334,6 +334,111 @@ public sealed class UpdateReconciliationIssueDto
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class PreviewReconciliationImportDto
|
||||
{
|
||||
[Required]
|
||||
[StringLength(50)]
|
||||
public string Provider { get; set; } = string.Empty;
|
||||
|
||||
public DateOnly BillDate { get; set; }
|
||||
public ReconciliationBillType BillType { get; set; } = ReconciliationBillType.Combined;
|
||||
|
||||
[Required]
|
||||
[StringLength(300)]
|
||||
public string SourceName { get; set; } = string.Empty;
|
||||
|
||||
public JsonElement Rows { get; set; } = JsonDefaults.Array();
|
||||
|
||||
public PreviewReconciliationImportCommand ToPreviewCommand() => new(Provider, BillDate, BillType, SourceName, Rows);
|
||||
|
||||
public ImportReconciliationCommand ToImportCommand() => new(Provider, BillDate, BillType, SourceName, Rows);
|
||||
}
|
||||
|
||||
public sealed class CreateAdjustmentVoucherDto
|
||||
{
|
||||
public Guid? IssueId { get; set; }
|
||||
public Guid? BatchId { get; set; }
|
||||
public Guid? ItemId { get; set; }
|
||||
public Guid? OrderId { get; set; }
|
||||
public Guid? PaymentId { get; set; }
|
||||
public Guid? RefundRequestId { get; set; }
|
||||
public CommerceAdjustmentDirection Direction { get; set; } = CommerceAdjustmentDirection.IncreaseRevenue;
|
||||
|
||||
[Range(1, int.MaxValue)]
|
||||
public int AmountCents { get; set; }
|
||||
|
||||
[StringLength(10)]
|
||||
public string? Currency { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(1000)]
|
||||
public string Reason { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(500)]
|
||||
public string? ProofAssetKey { get; set; }
|
||||
|
||||
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
|
||||
|
||||
public CreateAdjustmentVoucherCommand ToCommand() => new(
|
||||
IssueId,
|
||||
BatchId,
|
||||
ItemId,
|
||||
OrderId,
|
||||
PaymentId,
|
||||
RefundRequestId,
|
||||
Direction,
|
||||
AmountCents,
|
||||
Currency,
|
||||
Reason,
|
||||
ProofAssetKey,
|
||||
Metadata);
|
||||
}
|
||||
|
||||
public sealed class UpdateAdjustmentVoucherStatusDto
|
||||
{
|
||||
[Required]
|
||||
public Guid VoucherId { get; set; }
|
||||
|
||||
public CommerceAdjustmentVoucherStatus Status { get; set; } = CommerceAdjustmentVoucherStatus.PendingReview;
|
||||
|
||||
[StringLength(1000)]
|
||||
public string? Note { get; set; }
|
||||
|
||||
public UpdateAdjustmentVoucherStatusCommand ToCommand() => new(VoucherId, Status, Note);
|
||||
}
|
||||
|
||||
public sealed class RequestProviderBillJobDto
|
||||
{
|
||||
[Required]
|
||||
[StringLength(50)]
|
||||
public string Provider { get; set; } = string.Empty;
|
||||
|
||||
public DateOnly BillDate { get; set; }
|
||||
public ReconciliationBillType BillType { get; set; } = ReconciliationBillType.Combined;
|
||||
public DateTimeOffset? RunAfter { get; set; }
|
||||
|
||||
public RequestProviderBillJobCommand ToCommand() => new(Provider, BillDate, BillType, RunAfter);
|
||||
}
|
||||
|
||||
public sealed class RefundNotificationDto
|
||||
{
|
||||
[Required]
|
||||
[StringLength(100)]
|
||||
public string RefundNo { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(200)]
|
||||
public string? ProviderRefundNo { get; set; }
|
||||
|
||||
public CommerceRefundStatus Status { get; set; } = CommerceRefundStatus.Succeeded;
|
||||
|
||||
[StringLength(200)]
|
||||
public string? EventId { get; set; }
|
||||
|
||||
public JsonElement Payload { get; set; } = JsonDefaults.Object();
|
||||
|
||||
public RefundNotificationCommand ToCommand(string provider) => new(provider, RefundNo, ProviderRefundNo, Status, EventId, Payload);
|
||||
}
|
||||
|
||||
public sealed class UpdatePointExchangeOrderStatusDto
|
||||
{
|
||||
[Required]
|
||||
|
||||
Reference in New Issue
Block a user