66 lines
2.2 KiB
C#
66 lines
2.2 KiB
C#
using MediatR;
|
|
using System.Text.Json;
|
|
using TakeoutSaaS.Application.App.Billings.Commands;
|
|
using TakeoutSaaS.Application.App.Billings.Dto;
|
|
using TakeoutSaaS.Domain.Tenants.Entities;
|
|
using TakeoutSaaS.Domain.Tenants.Enums;
|
|
using TakeoutSaaS.Domain.Tenants.Repositories;
|
|
using TakeoutSaaS.Shared.Abstractions.Constants;
|
|
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
|
using TakeoutSaaS.Shared.Abstractions.Ids;
|
|
|
|
namespace TakeoutSaaS.Application.App.Billings.Handlers;
|
|
|
|
/// <summary>
|
|
/// 创建账单命令处理器。
|
|
/// </summary>
|
|
public sealed class CreateBillingCommandHandler(
|
|
ITenantRepository tenantRepository,
|
|
ITenantBillingRepository billingRepository,
|
|
IIdGenerator idGenerator)
|
|
: IRequestHandler<CreateBillingCommand, BillingDetailDto>
|
|
{
|
|
/// <inheritdoc />
|
|
public async Task<BillingDetailDto> Handle(CreateBillingCommand request, CancellationToken cancellationToken)
|
|
{
|
|
// 1. 校验租户存在
|
|
var tenant = await tenantRepository.FindByIdAsync(request.TenantId, cancellationToken);
|
|
if (tenant is null)
|
|
{
|
|
throw new BusinessException(ErrorCodes.NotFound, "租户不存在");
|
|
}
|
|
|
|
// 2. 构建账单实体
|
|
var now = DateTime.UtcNow;
|
|
var statementNo = $"BIL-{now:yyyyMMdd}-{idGenerator.NextId()}";
|
|
var lineItemsJson = JsonSerializer.Serialize(request.LineItems);
|
|
|
|
var billing = new TenantBillingStatement
|
|
{
|
|
TenantId = request.TenantId,
|
|
StatementNo = statementNo,
|
|
BillingType = request.BillingType,
|
|
SubscriptionId = null,
|
|
PeriodStart = now,
|
|
PeriodEnd = now,
|
|
AmountDue = request.AmountDue,
|
|
DiscountAmount = 0m,
|
|
TaxAmount = 0m,
|
|
AmountPaid = 0m,
|
|
Currency = "CNY",
|
|
Status = TenantBillingStatus.Pending,
|
|
DueDate = request.DueDate,
|
|
LineItemsJson = lineItemsJson,
|
|
Notes = request.Notes
|
|
};
|
|
|
|
// 3. 持久化账单
|
|
await billingRepository.AddAsync(billing, cancellationToken);
|
|
await billingRepository.SaveChangesAsync(cancellationToken);
|
|
|
|
// 4. 返回详情 DTO
|
|
return billing.ToBillingDetailDto([], tenant.Name);
|
|
}
|
|
}
|
|
|