Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展 Confidence: medium Scope-risk: broad Directive: 后续修改需保持审计事件与业务事务边界一致 Tested: git diff --cached --check Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
55 lines
1.8 KiB
Go
55 lines
1.8 KiB
Go
package notification
|
|
|
|
import (
|
|
"context"
|
|
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/clause"
|
|
|
|
"github.com/break/junhong_cmp_fiber/internal/model"
|
|
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
|
)
|
|
|
|
// Repository 提供站内通知幂等写入能力。
|
|
type Repository struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewRepository 创建站内通知持久化 Adapter。
|
|
func NewRepository(db *gorm.DB) *Repository {
|
|
return &Repository{db: db}
|
|
}
|
|
|
|
// DB 返回通知 Repository 使用的数据库连接。
|
|
func (r *Repository) DB() *gorm.DB { return r.db }
|
|
|
|
// WithTx 返回绑定指定事务的通知 Repository。
|
|
func (r *Repository) WithTx(tx *gorm.DB) *Repository { return &Repository{db: tx} }
|
|
|
|
// CreateIdempotent 以事件、接收人类型和接收人 ID 唯一键幂等写入通知。
|
|
func (r *Repository) CreateIdempotent(ctx context.Context, notification *model.Notification) (bool, error) {
|
|
result := r.db.WithContext(ctx).Clauses(clause.OnConflict{
|
|
Columns: []clause.Column{{Name: "event_id"}, {Name: "recipient_kind"}, {Name: "recipient_id"}},
|
|
DoNothing: true,
|
|
}).Create(notification)
|
|
return result.RowsAffected == 1, result.Error
|
|
}
|
|
|
|
// IsActiveAccount 判断明确后台账号是否仍启用且未软删除。
|
|
func (r *Repository) IsActiveAccount(ctx context.Context, accountID uint) (bool, error) {
|
|
var count int64
|
|
err := r.db.WithContext(ctx).Model(&model.Account{}).
|
|
Where("id = ? AND status = ?", accountID, constants.StatusEnabled).
|
|
Count(&count).Error
|
|
return count == 1, err
|
|
}
|
|
|
|
// IsActivePersonalCustomer 判断明确个人客户是否仍启用且未软删除。
|
|
func (r *Repository) IsActivePersonalCustomer(ctx context.Context, customerID uint) (bool, error) {
|
|
var count int64
|
|
err := r.db.WithContext(ctx).Model(&model.PersonalCustomer{}).
|
|
Where("id = ? AND status = ?", customerID, constants.StatusEnabled).
|
|
Count(&count).Error
|
|
return count == 1, err
|
|
}
|