| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | package entities | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | import ( | 
					
						
							|  |  |  |  | 	"fmt" | 
					
						
							|  |  |  |  | 	"time" | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	"github.com/google/uuid" | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | 	"github.com/shopspring/decimal" | 
					
						
							|  |  |  |  | 	"gorm.io/gorm" | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // Wallet 钱包聚合根 | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | // 用户数字钱包的核心信息,支持多种钱包类型和精确的余额管理 | 
					
						
							|  |  |  |  | // 使用decimal类型确保金额计算的精确性,避免浮点数精度问题 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // 支持欠费(余额<0),但只允许扣到小于0一次,之后不能再扣 | 
					
						
							|  |  |  |  | // 新建钱包时可配置默认额度 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | type Wallet struct { | 
					
						
							|  |  |  |  | 	// 基础标识 | 
					
						
							|  |  |  |  | 	ID     string `gorm:"primaryKey;type:varchar(36)" json:"id" comment:"钱包唯一标识"` | 
					
						
							|  |  |  |  | 	UserID string `gorm:"type:varchar(36);not null;uniqueIndex" json:"user_id" comment:"关联用户ID"` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 钱包状态 - 钱包的基本状态信息 | 
					
						
							|  |  |  |  | 	IsActive bool            `gorm:"default:true" json:"is_active" comment:"钱包是否激活"` | 
					
						
							|  |  |  |  | 	Balance  decimal.Decimal `gorm:"type:decimal(20,8);default:0" json:"balance" comment:"钱包余额(精确到8位小数)"` | 
					
						
							| 
									
										
										
										
											2025-09-12 01:15:09 +08:00
										 |  |  |  | 	Version  int64           `gorm:"default:0" json:"version" comment:"乐观锁版本号"` | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 时间戳字段 | 
					
						
							|  |  |  |  | 	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 (Wallet) TableName() string { | 
					
						
							|  |  |  |  | 	return "wallets" | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // IsZeroBalance 检查余额是否为零 | 
					
						
							|  |  |  |  | func (w *Wallet) IsZeroBalance() bool { | 
					
						
							|  |  |  |  | 	return w.Balance.IsZero() | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // HasSufficientBalance 检查是否有足够余额(允许透支额度) | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | func (w *Wallet) HasSufficientBalance(amount decimal.Decimal) bool { | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 允许扣到额度下限 | 
					
						
							|  |  |  |  | 	return w.Balance.Sub(amount).GreaterThanOrEqual(decimal.Zero) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // IsArrears 是否欠费(余额<0) | 
					
						
							|  |  |  |  | func (w *Wallet) IsArrears() bool { | 
					
						
							|  |  |  |  | 	return w.Balance.LessThan(decimal.Zero) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // IsLowBalance 是否余额较低(余额<300) | 
					
						
							|  |  |  |  | func (w *Wallet) IsLowBalance() bool { | 
					
						
							|  |  |  |  | 	return w.Balance.LessThan(decimal.NewFromInt(300)) | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // GetBalanceStatus 获取余额状态 | 
					
						
							|  |  |  |  | func (w *Wallet) GetBalanceStatus() string { | 
					
						
							|  |  |  |  | 	if w.IsArrears() { | 
					
						
							|  |  |  |  | 		return "arrears" // 欠费 | 
					
						
							|  |  |  |  | 	} else if w.IsLowBalance() { | 
					
						
							|  |  |  |  | 		return "low" // 余额较低 | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		return "normal" // 正常 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // AddBalance 增加余额(只做加法,业务规则由服务层控制是否允许充值) | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | func (w *Wallet) AddBalance(amount decimal.Decimal) { | 
					
						
							|  |  |  |  | 	w.Balance = w.Balance.Add(amount) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // SubtractBalance 扣减余额,含欠费业务规则 | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | func (w *Wallet) SubtractBalance(amount decimal.Decimal) error { | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	if w.Balance.LessThan(decimal.Zero) { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("已欠费,不能再扣款") | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	newBalance := w.Balance.Sub(amount) | 
					
						
							|  |  |  |  | 	w.Balance = newBalance | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetFormattedBalance 获取格式化的余额字符串 | 
					
						
							|  |  |  |  | func (w *Wallet) GetFormattedBalance() string { | 
					
						
							|  |  |  |  | 	return w.Balance.String() | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | // BeforeCreate GORM钩子:创建前自动生成UUID | 
					
						
							|  |  |  |  | func (w *Wallet) BeforeCreate(tx *gorm.DB) error { | 
					
						
							|  |  |  |  | 	if w.ID == "" { | 
					
						
							|  |  |  |  | 		w.ID = uuid.New().String() | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | // NewWallet 工厂方法 | 
					
						
							|  |  |  |  | func NewWallet(userID string, defaultCreditLimit decimal.Decimal) *Wallet { | 
					
						
							|  |  |  |  | 	return &Wallet{ | 
					
						
							|  |  |  |  | 		UserID:   userID, | 
					
						
							|  |  |  |  | 		IsActive: true, | 
					
						
							|  |  |  |  | 		Balance:  defaultCreditLimit, | 
					
						
							|  |  |  |  | 		Version:  0, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } |