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,
|
||
)
|
||
} |