230 lines
7.2 KiB
Go
230 lines
7.2 KiB
Go
package events
|
||
|
||
import (
|
||
"context"
|
||
"encoding/json"
|
||
"fmt"
|
||
"time"
|
||
|
||
"go.uber.org/zap"
|
||
|
||
"tyapi-server/internal/domains/finance/events"
|
||
"tyapi-server/internal/infrastructure/external/email"
|
||
"tyapi-server/internal/shared/interfaces"
|
||
)
|
||
|
||
// InvoiceEventHandler 发票事件处理器
|
||
type InvoiceEventHandler struct {
|
||
logger *zap.Logger
|
||
emailService *email.QQEmailService
|
||
name string
|
||
eventTypes []string
|
||
isAsync bool
|
||
}
|
||
|
||
// NewInvoiceEventHandler 创建发票事件处理器
|
||
func NewInvoiceEventHandler(logger *zap.Logger, emailService *email.QQEmailService) *InvoiceEventHandler {
|
||
return &InvoiceEventHandler{
|
||
logger: logger,
|
||
emailService: emailService,
|
||
name: "invoice-event-handler",
|
||
eventTypes: []string{
|
||
"InvoiceApplicationCreated",
|
||
"InvoiceApplicationApproved",
|
||
"InvoiceApplicationRejected",
|
||
"InvoiceFileUploaded",
|
||
},
|
||
isAsync: true,
|
||
}
|
||
}
|
||
|
||
// GetName 获取处理器名称
|
||
func (h *InvoiceEventHandler) GetName() string {
|
||
return h.name
|
||
}
|
||
|
||
// GetEventTypes 获取支持的事件类型
|
||
func (h *InvoiceEventHandler) GetEventTypes() []string {
|
||
return h.eventTypes
|
||
}
|
||
|
||
// IsAsync 是否为异步处理器
|
||
func (h *InvoiceEventHandler) IsAsync() bool {
|
||
return h.isAsync
|
||
}
|
||
|
||
// GetRetryConfig 获取重试配置
|
||
func (h *InvoiceEventHandler) GetRetryConfig() interfaces.RetryConfig {
|
||
return interfaces.RetryConfig{
|
||
MaxRetries: 3,
|
||
RetryDelay: 5 * time.Second,
|
||
BackoffFactor: 2.0,
|
||
MaxDelay: 30 * time.Second,
|
||
}
|
||
}
|
||
|
||
// Handle 处理事件
|
||
func (h *InvoiceEventHandler) Handle(ctx context.Context, event interfaces.Event) error {
|
||
h.logger.Info("🔄 开始处理发票事件",
|
||
zap.String("event_type", event.GetType()),
|
||
zap.String("event_id", event.GetID()),
|
||
zap.String("aggregate_id", event.GetAggregateID()),
|
||
zap.String("handler_name", h.GetName()),
|
||
zap.Time("event_timestamp", event.GetTimestamp()),
|
||
)
|
||
|
||
switch event.GetType() {
|
||
case "InvoiceApplicationCreated":
|
||
h.logger.Info("📝 处理发票申请创建事件")
|
||
return h.handleInvoiceApplicationCreated(ctx, event)
|
||
case "InvoiceApplicationApproved":
|
||
h.logger.Info("✅ 处理发票申请通过事件")
|
||
return h.handleInvoiceApplicationApproved(ctx, event)
|
||
case "InvoiceApplicationRejected":
|
||
h.logger.Info("❌ 处理发票申请拒绝事件")
|
||
return h.handleInvoiceApplicationRejected(ctx, event)
|
||
case "InvoiceFileUploaded":
|
||
h.logger.Info("📎 处理发票文件上传事件")
|
||
return h.handleInvoiceFileUploaded(ctx, event)
|
||
default:
|
||
h.logger.Warn("⚠️ 未知的发票事件类型", zap.String("event_type", event.GetType()))
|
||
return nil
|
||
}
|
||
}
|
||
|
||
// handleInvoiceApplicationCreated 处理发票申请创建事件
|
||
func (h *InvoiceEventHandler) handleInvoiceApplicationCreated(ctx context.Context, event interfaces.Event) error {
|
||
h.logger.Info("发票申请已创建",
|
||
zap.String("application_id", event.GetAggregateID()),
|
||
)
|
||
|
||
// 这里可以发送通知给管理员,告知有新的发票申请
|
||
// 暂时只记录日志
|
||
return nil
|
||
}
|
||
|
||
// handleInvoiceApplicationApproved 处理发票申请通过事件
|
||
func (h *InvoiceEventHandler) handleInvoiceApplicationApproved(ctx context.Context, event interfaces.Event) error {
|
||
h.logger.Info("发票申请已通过",
|
||
zap.String("application_id", event.GetAggregateID()),
|
||
)
|
||
|
||
// 这里可以发送通知给用户,告知发票申请已通过
|
||
// 暂时只记录日志
|
||
return nil
|
||
}
|
||
|
||
// handleInvoiceApplicationRejected 处理发票申请拒绝事件
|
||
func (h *InvoiceEventHandler) handleInvoiceApplicationRejected(ctx context.Context, event interfaces.Event) error {
|
||
h.logger.Info("发票申请被拒绝",
|
||
zap.String("application_id", event.GetAggregateID()),
|
||
)
|
||
|
||
// 这里可以发送邮件通知用户,告知发票申请被拒绝
|
||
// 暂时只记录日志
|
||
return nil
|
||
}
|
||
|
||
// handleInvoiceFileUploaded 处理发票文件上传事件
|
||
func (h *InvoiceEventHandler) handleInvoiceFileUploaded(ctx context.Context, event interfaces.Event) error {
|
||
h.logger.Info("📎 发票文件已上传事件开始处理",
|
||
zap.String("invoice_id", event.GetAggregateID()),
|
||
zap.String("event_id", event.GetID()),
|
||
)
|
||
|
||
// 解析事件数据
|
||
payload := event.GetPayload()
|
||
if payload == nil {
|
||
h.logger.Error("❌ 事件数据为空")
|
||
return fmt.Errorf("事件数据为空")
|
||
}
|
||
|
||
h.logger.Info("📋 事件数据解析开始",
|
||
zap.Any("payload_type", fmt.Sprintf("%T", payload)),
|
||
)
|
||
|
||
// 将payload转换为JSON,然后解析为InvoiceFileUploadedEvent
|
||
payloadBytes, err := json.Marshal(payload)
|
||
if err != nil {
|
||
h.logger.Error("❌ 序列化事件数据失败", zap.Error(err))
|
||
return fmt.Errorf("序列化事件数据失败: %w", err)
|
||
}
|
||
|
||
h.logger.Info("📄 事件数据序列化成功",
|
||
zap.String("payload_json", string(payloadBytes)),
|
||
)
|
||
|
||
var fileUploadedEvent events.InvoiceFileUploadedEvent
|
||
err = json.Unmarshal(payloadBytes, &fileUploadedEvent)
|
||
if err != nil {
|
||
h.logger.Error("❌ 解析发票文件上传事件失败", zap.Error(err))
|
||
return fmt.Errorf("解析发票文件上传事件失败: %w", err)
|
||
}
|
||
|
||
h.logger.Info("✅ 事件数据解析成功",
|
||
zap.String("invoice_id", fileUploadedEvent.InvoiceID),
|
||
zap.String("user_id", fileUploadedEvent.UserID),
|
||
zap.String("receiving_email", fileUploadedEvent.ReceivingEmail),
|
||
zap.String("file_name", fileUploadedEvent.FileName),
|
||
zap.String("file_url", fileUploadedEvent.FileURL),
|
||
zap.String("company_name", fileUploadedEvent.CompanyName),
|
||
zap.String("amount", fileUploadedEvent.Amount.String()),
|
||
zap.String("invoice_type", string(fileUploadedEvent.InvoiceType)),
|
||
)
|
||
|
||
// 发送发票邮件给用户
|
||
return h.sendInvoiceEmail(ctx, &fileUploadedEvent)
|
||
}
|
||
|
||
// sendInvoiceEmail 发送发票邮件
|
||
func (h *InvoiceEventHandler) sendInvoiceEmail(ctx context.Context, event *events.InvoiceFileUploadedEvent) error {
|
||
h.logger.Info("📧 开始发送发票邮件",
|
||
zap.String("invoice_id", event.InvoiceID),
|
||
zap.String("user_id", event.UserID),
|
||
zap.String("receiving_email", event.ReceivingEmail),
|
||
zap.String("file_name", event.FileName),
|
||
zap.String("file_url", event.FileURL),
|
||
)
|
||
|
||
// 构建邮件数据
|
||
emailData := &email.InvoiceEmailData{
|
||
CompanyName: event.CompanyName,
|
||
Amount: event.Amount.String(),
|
||
InvoiceType: event.InvoiceType.GetDisplayName(),
|
||
FileURL: event.FileURL,
|
||
FileName: event.FileName,
|
||
ReceivingEmail: event.ReceivingEmail,
|
||
ApprovedAt: event.UploadedAt.Format("2006-01-02 15:04:05"),
|
||
}
|
||
|
||
h.logger.Info("📋 邮件数据构建完成",
|
||
zap.String("company_name", emailData.CompanyName),
|
||
zap.String("amount", emailData.Amount),
|
||
zap.String("invoice_type", emailData.InvoiceType),
|
||
zap.String("file_url", emailData.FileURL),
|
||
zap.String("file_name", emailData.FileName),
|
||
zap.String("receiving_email", emailData.ReceivingEmail),
|
||
zap.String("approved_at", emailData.ApprovedAt),
|
||
)
|
||
|
||
// 发送邮件
|
||
h.logger.Info("🚀 开始调用邮件服务发送邮件")
|
||
err := h.emailService.SendInvoiceEmail(ctx, emailData)
|
||
if err != nil {
|
||
h.logger.Error("❌ 发送发票邮件失败",
|
||
zap.String("invoice_id", event.InvoiceID),
|
||
zap.String("receiving_email", event.ReceivingEmail),
|
||
zap.Error(err),
|
||
)
|
||
return fmt.Errorf("发送发票邮件失败: %w", err)
|
||
}
|
||
|
||
h.logger.Info("✅ 发票邮件发送成功",
|
||
zap.String("invoice_id", event.InvoiceID),
|
||
zap.String("receiving_email", event.ReceivingEmail),
|
||
)
|
||
|
||
return nil
|
||
}
|
||
|
||
|