feat(finance): 完成发票管理模块后端实现

This commit is contained in:
2026-03-04 16:48:58 +08:00
parent 21a689edec
commit c79e9bd6e8
33 changed files with 2970 additions and 0 deletions

View File

@@ -0,0 +1,199 @@
using TakeoutSaaS.Application.App.Finance.Invoice.Commands;
using TakeoutSaaS.Application.App.Finance.Invoice.Dto;
using TakeoutSaaS.Domain.Tenants.Entities;
using TakeoutSaaS.Domain.Tenants.Enums;
using TakeoutSaaS.Domain.Tenants.Repositories;
namespace TakeoutSaaS.Application.App.Finance.Invoice;
/// <summary>
/// 发票模块 DTO 构造器。
/// </summary>
internal static class FinanceInvoiceDtoFactory
{
public static FinanceInvoiceSettingDto CreateDefaultSettingDto()
{
return new FinanceInvoiceSettingDto
{
CompanyName = string.Empty,
TaxpayerNumber = string.Empty,
RegisteredAddress = null,
RegisteredPhone = null,
BankName = null,
BankAccount = null,
EnableElectronicNormalInvoice = true,
EnableElectronicSpecialInvoice = false,
EnableAutoIssue = false,
AutoIssueMaxAmount = 10_000m
};
}
public static FinanceInvoiceSettingDto ToSettingDto(TenantInvoiceSetting source)
{
return new FinanceInvoiceSettingDto
{
CompanyName = source.CompanyName,
TaxpayerNumber = source.TaxpayerNumber,
RegisteredAddress = source.RegisteredAddress,
RegisteredPhone = source.RegisteredPhone,
BankName = source.BankName,
BankAccount = source.BankAccount,
EnableElectronicNormalInvoice = source.EnableElectronicNormalInvoice,
EnableElectronicSpecialInvoice = source.EnableElectronicSpecialInvoice,
EnableAutoIssue = source.EnableAutoIssue,
AutoIssueMaxAmount = decimal.Round(source.AutoIssueMaxAmount, 2, MidpointRounding.AwayFromZero)
};
}
public static TenantInvoiceSetting CreateSettingEntity(
SaveFinanceInvoiceSettingCommand request,
string companyName,
string taxpayerNumber,
string? registeredAddress,
string? registeredPhone,
string? bankName,
string? bankAccount,
decimal autoIssueMaxAmount)
{
return new TenantInvoiceSetting
{
CompanyName = companyName,
TaxpayerNumber = taxpayerNumber,
RegisteredAddress = registeredAddress,
RegisteredPhone = registeredPhone,
BankName = bankName,
BankAccount = bankAccount,
EnableElectronicNormalInvoice = request.EnableElectronicNormalInvoice,
EnableElectronicSpecialInvoice = request.EnableElectronicSpecialInvoice,
EnableAutoIssue = request.EnableAutoIssue,
AutoIssueMaxAmount = autoIssueMaxAmount
};
}
public static void ApplySettingChanges(
TenantInvoiceSetting entity,
SaveFinanceInvoiceSettingCommand request,
string companyName,
string taxpayerNumber,
string? registeredAddress,
string? registeredPhone,
string? bankName,
string? bankAccount,
decimal autoIssueMaxAmount)
{
entity.CompanyName = companyName;
entity.TaxpayerNumber = taxpayerNumber;
entity.RegisteredAddress = registeredAddress;
entity.RegisteredPhone = registeredPhone;
entity.BankName = bankName;
entity.BankAccount = bankAccount;
entity.EnableElectronicNormalInvoice = request.EnableElectronicNormalInvoice;
entity.EnableElectronicSpecialInvoice = request.EnableElectronicSpecialInvoice;
entity.EnableAutoIssue = request.EnableAutoIssue;
entity.AutoIssueMaxAmount = autoIssueMaxAmount;
}
public static FinanceInvoiceStatsDto ToStatsDto(TenantInvoiceRecordStatsSnapshot source)
{
return new FinanceInvoiceStatsDto
{
CurrentMonthIssuedAmount = decimal.Round(source.CurrentMonthIssuedAmount, 2, MidpointRounding.AwayFromZero),
CurrentMonthIssuedCount = source.CurrentMonthIssuedCount,
PendingCount = source.PendingCount,
VoidedCount = source.VoidedCount
};
}
public static FinanceInvoiceRecordDto ToRecordDto(TenantInvoiceRecord source)
{
return new FinanceInvoiceRecordDto
{
RecordId = source.Id,
InvoiceNo = source.InvoiceNo,
ApplicantName = source.ApplicantName,
CompanyName = source.CompanyName,
InvoiceType = FinanceInvoiceMapping.ToInvoiceTypeText(source.InvoiceType),
InvoiceTypeText = FinanceInvoiceMapping.ToInvoiceTypeDisplayText(source.InvoiceType),
Amount = decimal.Round(source.Amount, 2, MidpointRounding.AwayFromZero),
OrderNo = source.OrderNo,
Status = FinanceInvoiceMapping.ToStatusText(source.Status),
StatusText = FinanceInvoiceMapping.ToStatusDisplayText(source.Status),
AppliedAt = source.AppliedAt
};
}
public static FinanceInvoiceRecordDetailDto ToRecordDetailDto(TenantInvoiceRecord source)
{
return new FinanceInvoiceRecordDetailDto
{
RecordId = source.Id,
InvoiceNo = source.InvoiceNo,
ApplicantName = source.ApplicantName,
CompanyName = source.CompanyName,
TaxpayerNumber = source.TaxpayerNumber,
InvoiceType = FinanceInvoiceMapping.ToInvoiceTypeText(source.InvoiceType),
InvoiceTypeText = FinanceInvoiceMapping.ToInvoiceTypeDisplayText(source.InvoiceType),
Amount = decimal.Round(source.Amount, 2, MidpointRounding.AwayFromZero),
OrderNo = source.OrderNo,
ContactEmail = source.ContactEmail,
ContactPhone = source.ContactPhone,
ApplyRemark = source.ApplyRemark,
Status = FinanceInvoiceMapping.ToStatusText(source.Status),
StatusText = FinanceInvoiceMapping.ToStatusDisplayText(source.Status),
AppliedAt = source.AppliedAt,
IssuedAt = source.IssuedAt,
IssuedByUserId = source.IssuedByUserId,
IssueRemark = source.IssueRemark,
VoidedAt = source.VoidedAt,
VoidedByUserId = source.VoidedByUserId,
VoidReason = source.VoidReason
};
}
public static FinanceInvoiceIssueResultDto ToIssueResultDto(TenantInvoiceRecord source)
{
return new FinanceInvoiceIssueResultDto
{
RecordId = source.Id,
InvoiceNo = source.InvoiceNo,
CompanyName = source.CompanyName,
Amount = decimal.Round(source.Amount, 2, MidpointRounding.AwayFromZero),
ContactEmail = source.ContactEmail,
IssuedAt = source.IssuedAt ?? DateTime.UtcNow,
Status = FinanceInvoiceMapping.ToStatusText(source.Status),
StatusText = FinanceInvoiceMapping.ToStatusDisplayText(source.Status)
};
}
public static TenantInvoiceRecord CreateRecordEntity(
long tenantId,
string invoiceNo,
string applicantName,
string companyName,
string? taxpayerNumber,
TenantInvoiceType invoiceType,
decimal amount,
string orderNo,
string? contactEmail,
string? contactPhone,
string? applyRemark,
DateTime appliedAt)
{
return new TenantInvoiceRecord
{
TenantId = tenantId,
InvoiceNo = invoiceNo,
ApplicantName = applicantName,
CompanyName = companyName,
TaxpayerNumber = taxpayerNumber,
InvoiceType = invoiceType,
Amount = amount,
OrderNo = orderNo,
ContactEmail = contactEmail,
ContactPhone = contactPhone,
ApplyRemark = applyRemark,
Status = TenantInvoiceStatus.Pending,
AppliedAt = appliedAt
};
}
}