Files
TakeoutSaaS.TenantApi/src/Application/TakeoutSaaS.Application/App/Billings/BillingMapping.cs
2026-02-17 12:12:01 +08:00

201 lines
7.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Text.Json;
using TakeoutSaaS.Application.App.Billings.Dto;
using TakeoutSaaS.Domain.Tenants.Entities;
namespace TakeoutSaaS.Application.App.Billings;
/// <summary>
/// 账单 DTO 映射助手。
/// </summary>
internal static class BillingMapping
{
/// <summary>
/// 将账单实体映射为账单 DTO旧版
/// </summary>
/// <param name="bill">账单实体。</param>
/// <param name="tenantName">租户名称。</param>
/// <returns>账单 DTO。</returns>
public static BillDto ToDto(this TenantBillingStatement bill, string? tenantName = null)
=> new()
{
Id = bill.Id,
TenantId = bill.TenantId,
TenantName = tenantName,
StatementNo = bill.StatementNo,
PeriodStart = bill.PeriodStart,
PeriodEnd = bill.PeriodEnd,
AmountDue = bill.AmountDue,
AmountPaid = bill.AmountPaid,
Status = bill.Status,
DueDate = bill.DueDate,
CreatedAt = bill.CreatedAt
};
/// <summary>
/// 将账单实体映射为账单列表 DTO新版
/// </summary>
/// <param name="billing">账单实体。</param>
/// <param name="tenantName">租户名称。</param>
/// <returns>账单列表 DTO。</returns>
public static BillingListDto ToBillingListDto(this TenantBillingStatement billing, string? tenantName = null)
=> new()
{
Id = billing.Id,
TenantId = billing.TenantId,
SubscriptionId = billing.SubscriptionId,
TenantName = tenantName ?? string.Empty,
StatementNo = billing.StatementNo,
BillingType = billing.BillingType,
Status = billing.Status,
PeriodStart = billing.PeriodStart,
PeriodEnd = billing.PeriodEnd,
AmountDue = billing.AmountDue,
AmountPaid = billing.AmountPaid,
DiscountAmount = billing.DiscountAmount,
TaxAmount = billing.TaxAmount,
TotalAmount = billing.CalculateTotalAmount(),
Currency = billing.Currency,
DueDate = billing.DueDate,
CreatedAt = billing.CreatedAt,
UpdatedAt = billing.UpdatedAt,
IsOverdue = billing.Status == TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus.Overdue
|| (billing.Status == TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus.Pending && billing.DueDate < DateTime.UtcNow),
OverdueDays = (billing.Status is TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus.Pending
or TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus.Overdue)
&& billing.DueDate < DateTime.UtcNow
? (int)(DateTime.UtcNow - billing.DueDate).TotalDays
: 0
};
/// <summary>
/// 将账单实体与支付记录映射为账单详情 DTO旧版
/// </summary>
/// <param name="bill">账单实体。</param>
/// <param name="payments">支付记录列表。</param>
/// <param name="tenantName">租户名称。</param>
/// <returns>账单详情 DTO。</returns>
public static BillDetailDto ToDetailDto(
this TenantBillingStatement bill,
List<TenantPayment> payments,
string? tenantName = null)
=> new()
{
Id = bill.Id,
TenantId = bill.TenantId,
TenantName = tenantName,
StatementNo = bill.StatementNo,
PeriodStart = bill.PeriodStart,
PeriodEnd = bill.PeriodEnd,
AmountDue = bill.AmountDue,
AmountPaid = bill.AmountPaid,
Status = bill.Status,
DueDate = bill.DueDate,
LineItemsJson = bill.LineItemsJson,
CreatedAt = bill.CreatedAt,
Payments = payments.Select(p => p.ToDto()).ToList()
};
/// <summary>
/// 将账单实体与支付记录映射为账单详情 DTO新版
/// </summary>
/// <param name="billing">账单实体。</param>
/// <param name="payments">支付记录列表。</param>
/// <param name="tenantName">租户名称。</param>
/// <returns>账单详情 DTO。</returns>
public static BillingDetailDto ToBillingDetailDto(
this TenantBillingStatement billing,
List<TenantPayment> payments,
string? tenantName = null)
{
// 反序列化账单明细
var lineItems = new List<BillingLineItemDto>();
if (!string.IsNullOrWhiteSpace(billing.LineItemsJson))
{
try
{
lineItems = JsonSerializer.Deserialize<List<BillingLineItemDto>>(billing.LineItemsJson) ?? [];
}
catch
{
lineItems = [];
}
}
return new BillingDetailDto
{
Id = billing.Id,
TenantId = billing.TenantId,
TenantName = tenantName ?? string.Empty,
SubscriptionId = billing.SubscriptionId,
StatementNo = billing.StatementNo,
BillingType = billing.BillingType,
Status = billing.Status,
PeriodStart = billing.PeriodStart,
PeriodEnd = billing.PeriodEnd,
AmountDue = billing.AmountDue,
AmountPaid = billing.AmountPaid,
DiscountAmount = billing.DiscountAmount,
TaxAmount = billing.TaxAmount,
TotalAmount = billing.CalculateTotalAmount(),
Currency = billing.Currency,
DueDate = billing.DueDate,
ReminderSentAt = billing.ReminderSentAt,
OverdueNotifiedAt = billing.OverdueNotifiedAt,
LineItemsJson = billing.LineItemsJson,
LineItems = lineItems,
Payments = payments.Select(p => p.ToPaymentRecordDto()).ToList(),
Notes = billing.Notes,
CreatedAt = billing.CreatedAt,
CreatedBy = billing.CreatedBy,
UpdatedAt = billing.UpdatedAt,
UpdatedBy = billing.UpdatedBy
};
}
/// <summary>
/// 将支付记录实体映射为支付 DTO旧版
/// </summary>
/// <param name="payment">支付记录实体。</param>
/// <returns>支付 DTO。</returns>
public static PaymentDto ToDto(this TenantPayment payment)
=> new()
{
Id = payment.Id,
BillingStatementId = payment.BillingStatementId,
Amount = payment.Amount,
Method = payment.Method,
Status = payment.Status,
TransactionNo = payment.TransactionNo,
ProofUrl = payment.ProofUrl,
PaidAt = payment.PaidAt,
Notes = payment.Notes,
CreatedAt = payment.CreatedAt
};
/// <summary>
/// 将支付记录实体映射为支付记录 DTO新版
/// </summary>
/// <param name="payment">支付记录实体。</param>
/// <returns>支付记录 DTO。</returns>
public static PaymentRecordDto ToPaymentRecordDto(this TenantPayment payment)
=> new()
{
Id = payment.Id,
TenantId = payment.TenantId,
BillingId = payment.BillingStatementId,
Amount = payment.Amount,
Method = payment.Method,
Status = payment.Status,
TransactionNo = payment.TransactionNo,
ProofUrl = payment.ProofUrl,
IsVerified = payment.VerifiedAt.HasValue,
PaidAt = payment.PaidAt,
VerifiedBy = payment.VerifiedBy,
VerifiedAt = payment.VerifiedAt,
RefundReason = payment.RefundReason,
RefundedAt = payment.RefundedAt,
Notes = payment.Notes,
CreatedAt = payment.CreatedAt
};
}