feat: 完善手动创建租户功能,添加账单明细和支付记录
1. 手动创建租户时自动生成账单明细(LineItemsJson) 2. 账单状态为已支付时自动创建支付记录 3. 租户列表接口返回联系人信息和认证状态 4. 账单详情接口返回支付记录和解析后的账单明细 5. 管理员账号自动复用租户联系人信息 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -86,6 +86,11 @@ public sealed record BillingDetailDto
|
||||
/// </summary>
|
||||
public string? LineItemsJson { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 账单明细列表(从 LineItemsJson 解析)。
|
||||
/// </summary>
|
||||
public IReadOnlyList<BillingLineItemDto>? LineItems { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注。
|
||||
/// </summary>
|
||||
@@ -195,3 +200,34 @@ public sealed record PaymentRecordDto
|
||||
/// </summary>
|
||||
public DateTime CreatedAt { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 账单明细项 DTO。
|
||||
/// </summary>
|
||||
public sealed record BillingLineItemDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 项目名称。
|
||||
/// </summary>
|
||||
public string Name { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 单价。
|
||||
/// </summary>
|
||||
public decimal UnitPrice { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 数量。
|
||||
/// </summary>
|
||||
public int Quantity { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 金额。
|
||||
/// </summary>
|
||||
public decimal Amount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注。
|
||||
/// </summary>
|
||||
public string? Remark { get; init; }
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Text.Json;
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.App.Billings.Contracts;
|
||||
using TakeoutSaaS.Application.App.Billings.Queries;
|
||||
@@ -25,7 +26,43 @@ public sealed class GetBillingDetailQueryHandler(IBillingRepository billingRepos
|
||||
return null;
|
||||
}
|
||||
|
||||
// 3. 映射为 DTO 并返回(支付记录暂时返回空列表)
|
||||
// 3. 查询支付记录
|
||||
var payments = await billingRepository.GetPaymentsByBillingIdAsync(request.BillingId, cancellationToken);
|
||||
|
||||
// 4. 映射支付记录为 DTO
|
||||
var paymentDtos = payments.Select(p => new PaymentRecordDto
|
||||
{
|
||||
Id = p.Id,
|
||||
BillingStatementId = p.BillingStatementId,
|
||||
Amount = p.Amount,
|
||||
Method = (int)p.Method,
|
||||
Status = (int)p.Status,
|
||||
TransactionNo = p.TransactionNo,
|
||||
ProofUrl = p.ProofUrl,
|
||||
PaidAt = p.PaidAt,
|
||||
Notes = p.Notes,
|
||||
VerifiedBy = p.VerifiedBy,
|
||||
VerifiedAt = p.VerifiedAt,
|
||||
RefundReason = p.RefundReason,
|
||||
RefundedAt = p.RefundedAt,
|
||||
CreatedAt = p.CreatedAt
|
||||
}).ToList();
|
||||
|
||||
// 5. 解析账单明细 JSON
|
||||
List<BillingLineItemDto>? lineItems = null;
|
||||
if (!string.IsNullOrEmpty(detail.LineItemsJson))
|
||||
{
|
||||
try
|
||||
{
|
||||
lineItems = JsonSerializer.Deserialize<List<BillingLineItemDto>>(detail.LineItemsJson);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 解析失败时忽略
|
||||
}
|
||||
}
|
||||
|
||||
// 6. 映射为 DTO 并返回
|
||||
return new BillingDetailDto
|
||||
{
|
||||
Id = detail.Id,
|
||||
@@ -43,12 +80,13 @@ public sealed class GetBillingDetailQueryHandler(IBillingRepository billingRepos
|
||||
Status = detail.Status,
|
||||
DueDate = detail.DueDate,
|
||||
LineItemsJson = detail.LineItemsJson,
|
||||
LineItems = lineItems,
|
||||
Notes = detail.Notes,
|
||||
OverdueNotifiedAt = detail.OverdueNotifiedAt,
|
||||
ReminderSentAt = detail.ReminderSentAt,
|
||||
CreatedAt = detail.CreatedAt,
|
||||
UpdatedAt = detail.UpdatedAt,
|
||||
Payments = []
|
||||
Payments = paymentDtos
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user