163 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			163 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|  | package entities | |||
|  | 
 | |||
|  | import ( | |||
|  | 	"time" | |||
|  | 
 | |||
|  | 	"github.com/google/uuid" | |||
|  | 	"github.com/shopspring/decimal" | |||
|  | 	"gorm.io/gorm" | |||
|  | 
 | |||
|  | 	"tyapi-server/internal/domains/finance/value_objects" | |||
|  | ) | |||
|  | 
 | |||
|  | // ApplicationStatus 申请状态枚举 | |||
|  | type ApplicationStatus string | |||
|  | 
 | |||
|  | const ( | |||
|  | 	ApplicationStatusPending   ApplicationStatus = "pending"   // 待处理 | |||
|  | 	ApplicationStatusCompleted ApplicationStatus = "completed" // 已完成(已上传发票) | |||
|  | 	ApplicationStatusRejected  ApplicationStatus = "rejected"  // 已拒绝 | |||
|  | ) | |||
|  | 
 | |||
|  | // InvoiceApplication 发票申请聚合根 | |||
|  | type InvoiceApplication struct { | |||
|  | 	// 基础标识 | |||
|  | 	ID          string `gorm:"primaryKey;type:varchar(36)" json:"id" comment:"申请唯一标识"` | |||
|  | 	UserID      string `gorm:"type:varchar(36);not null;index" json:"user_id" comment:"申请用户ID"` | |||
|  | 
 | |||
|  | 	// 申请信息 | |||
|  | 	InvoiceType value_objects.InvoiceType `gorm:"type:varchar(20);not null" json:"invoice_type" comment:"发票类型"` | |||
|  | 	Amount      decimal.Decimal           `gorm:"type:decimal(20,8);not null" json:"amount" comment:"申请金额"` | |||
|  | 	Status      ApplicationStatus         `gorm:"type:varchar(20);not null;default:'pending';index" json:"status" comment:"申请状态"` | |||
|  | 
 | |||
|  | 	// 开票信息快照(申请时的信息,用于历史记录追踪) | |||
|  | 	CompanyName    string `gorm:"type:varchar(200);not null" json:"company_name" comment:"公司名称"` | |||
|  | 	TaxpayerID     string `gorm:"type:varchar(50);not null" json:"taxpayer_id" comment:"纳税人识别号"` | |||
|  | 	BankName       string `gorm:"type:varchar(100)" json:"bank_name" comment:"开户银行"` | |||
|  | 	BankAccount    string `gorm:"type:varchar(50)" json:"bank_account" comment:"银行账号"` | |||
|  | 	CompanyAddress string `gorm:"type:varchar(500)" json:"company_address" comment:"企业地址"` | |||
|  | 	CompanyPhone   string `gorm:"type:varchar(20)" json:"company_phone" comment:"企业电话"` | |||
|  | 	ReceivingEmail string `gorm:"type:varchar(100);not null" json:"receiving_email" comment:"发票接收邮箱"` | |||
|  | 	 | |||
|  | 	// 开票信息引用(关联到用户开票信息表,用于模板功能) | |||
|  | 	UserInvoiceInfoID string `gorm:"type:varchar(36);not null" json:"user_invoice_info_id" comment:"用户开票信息ID"` | |||
|  | 
 | |||
|  | 	// 文件信息(申请通过后才有) | |||
|  | 	FileID       *string    `gorm:"type:varchar(200)" json:"file_id,omitempty" comment:"文件ID"` | |||
|  | 	FileName     *string    `gorm:"type:varchar(200)" json:"file_name,omitempty" comment:"文件名"` | |||
|  | 	FileSize     *int64     `json:"file_size,omitempty" comment:"文件大小"` | |||
|  | 	FileURL      *string    `gorm:"type:varchar(500)" json:"file_url,omitempty" comment:"文件URL"` | |||
|  | 	 | |||
|  | 	// 处理信息 | |||
|  | 	ProcessedBy   *string    `gorm:"type:varchar(36)" json:"processed_by,omitempty" comment:"处理人ID"` | |||
|  | 	ProcessedAt   *time.Time `json:"processed_at,omitempty" comment:"处理时间"` | |||
|  | 	RejectReason  *string    `gorm:"type:varchar(500)" json:"reject_reason,omitempty" comment:"拒绝原因"` | |||
|  | 	AdminNotes    *string    `gorm:"type:varchar(500)" json:"admin_notes,omitempty" comment:"管理员备注"` | |||
|  | 
 | |||
|  | 	// 时间戳字段 | |||
|  | 	CreatedAt time.Time      `gorm:"autoCreateTime" json:"created_at" comment:"创建时间"` | |||
|  | 	UpdatedAt time.Time      `gorm:"autoUpdateTime" json:"updated_at" comment:"更新时间"` | |||
|  | 	DeletedAt gorm.DeletedAt `gorm:"index" json:"-" comment:"软删除时间"` | |||
|  | } | |||
|  | 
 | |||
|  | // TableName 指定数据库表名 | |||
|  | func (InvoiceApplication) TableName() string { | |||
|  | 	return "invoice_applications" | |||
|  | } | |||
|  | 
 | |||
|  | // BeforeCreate GORM钩子:创建前自动生成UUID | |||
|  | func (ia *InvoiceApplication) BeforeCreate(tx *gorm.DB) error { | |||
|  | 	if ia.ID == "" { | |||
|  | 		ia.ID = uuid.New().String() | |||
|  | 	} | |||
|  | 	return nil | |||
|  | } | |||
|  | 
 | |||
|  | // IsPending 检查是否为待处理状态 | |||
|  | func (ia *InvoiceApplication) IsPending() bool { | |||
|  | 	return ia.Status == ApplicationStatusPending | |||
|  | } | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | // IsCompleted 检查是否为已完成状态 | |||
|  | func (ia *InvoiceApplication) IsCompleted() bool { | |||
|  | 	return ia.Status == ApplicationStatusCompleted | |||
|  | } | |||
|  | 
 | |||
|  | // IsRejected 检查是否为已拒绝状态 | |||
|  | func (ia *InvoiceApplication) IsRejected() bool { | |||
|  | 	return ia.Status == ApplicationStatusRejected | |||
|  | } | |||
|  | 
 | |||
|  | // CanProcess 检查是否可以处理 | |||
|  | func (ia *InvoiceApplication) CanProcess() bool { | |||
|  | 	return ia.IsPending() | |||
|  | } | |||
|  | 
 | |||
|  | // CanReject 检查是否可以拒绝 | |||
|  | func (ia *InvoiceApplication) CanReject() bool { | |||
|  | 	return ia.IsPending() | |||
|  | } | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | // MarkCompleted 标记为已完成 | |||
|  | func (ia *InvoiceApplication) MarkCompleted(processedBy string) { | |||
|  | 	ia.Status = ApplicationStatusCompleted | |||
|  | 	ia.ProcessedBy = &processedBy | |||
|  | 	now := time.Now() | |||
|  | 	ia.ProcessedAt = &now | |||
|  | } | |||
|  | 
 | |||
|  | // MarkRejected 标记为已拒绝 | |||
|  | func (ia *InvoiceApplication) MarkRejected(reason string, processedBy string) { | |||
|  | 	ia.Status = ApplicationStatusRejected | |||
|  | 	ia.RejectReason = &reason | |||
|  | 	ia.ProcessedBy = &processedBy | |||
|  | 	now := time.Now() | |||
|  | 	ia.ProcessedAt = &now | |||
|  | } | |||
|  | 
 | |||
|  | // SetFileInfo 设置文件信息 | |||
|  | func (ia *InvoiceApplication) SetFileInfo(fileID, fileName, fileURL string, fileSize int64) { | |||
|  | 	ia.FileID = &fileID | |||
|  | 	ia.FileName = &fileName | |||
|  | 	ia.FileURL = &fileURL | |||
|  | 	ia.FileSize = &fileSize | |||
|  | } | |||
|  | 
 | |||
|  | // NewInvoiceApplication 工厂方法 | |||
|  | func NewInvoiceApplication(userID string, invoiceType value_objects.InvoiceType, amount decimal.Decimal, userInvoiceInfoID string) *InvoiceApplication { | |||
|  | 	return &InvoiceApplication{ | |||
|  | 		UserID:             userID, | |||
|  | 		InvoiceType:        invoiceType, | |||
|  | 		Amount:             amount, | |||
|  | 		Status:             ApplicationStatusPending, | |||
|  | 		UserInvoiceInfoID:  userInvoiceInfoID, | |||
|  | 	} | |||
|  | } | |||
|  | 
 | |||
|  | // SetInvoiceInfoSnapshot 设置开票信息快照 | |||
|  | func (ia *InvoiceApplication) SetInvoiceInfoSnapshot(info *value_objects.InvoiceInfo) { | |||
|  | 	ia.CompanyName = info.CompanyName | |||
|  | 	ia.TaxpayerID = info.TaxpayerID | |||
|  | 	ia.BankName = info.BankName | |||
|  | 	ia.BankAccount = info.BankAccount | |||
|  | 	ia.CompanyAddress = info.CompanyAddress | |||
|  | 	ia.CompanyPhone = info.CompanyPhone | |||
|  | 	ia.ReceivingEmail = info.ReceivingEmail | |||
|  | } | |||
|  | 
 | |||
|  | // GetInvoiceInfoSnapshot 获取开票信息快照 | |||
|  | func (ia *InvoiceApplication) GetInvoiceInfoSnapshot() *value_objects.InvoiceInfo { | |||
|  | 	return value_objects.NewInvoiceInfo( | |||
|  | 		ia.CompanyName, | |||
|  | 		ia.TaxpayerID, | |||
|  | 		ia.BankName, | |||
|  | 		ia.BankAccount, | |||
|  | 		ia.CompanyAddress, | |||
|  | 		ia.CompanyPhone, | |||
|  | 		ia.ReceivingEmail, | |||
|  | 	) | |||
|  | }  |