162 lines
5.9 KiB
Go
162 lines
5.9 KiB
Go
package business
|
|
|
|
import (
|
|
"context"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/clause"
|
|
"kra/internal/biz/business"
|
|
)
|
|
|
|
type bindingLockPO struct {
|
|
SourceDB string `gorm:"column:source_db;primaryKey;size:50"`
|
|
PlatformBusierID uint64 `gorm:"primaryKey;autoIncrement:false"`
|
|
}
|
|
|
|
func (bindingLockPO) TableName() string { return "sys_business_binding_locks" }
|
|
|
|
type bindingRepo struct{ data Provider }
|
|
|
|
func NewBindingRepo(data Provider) business.BindingRepo { return &bindingRepo{data: data} }
|
|
|
|
type bindingTxKey struct{}
|
|
|
|
func (r *bindingRepo) db(ctx context.Context) *gorm.DB {
|
|
if tx, ok := ctx.Value(bindingTxKey{}).(*gorm.DB); ok {
|
|
return tx.WithContext(ctx)
|
|
}
|
|
return r.data.DB().WithContext(ctx)
|
|
}
|
|
func (r *bindingRepo) WithPlatformLock(ctx context.Context, key business.PlatformKey, fn func(context.Context) error) error {
|
|
err := r.data.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
// 单独的键锁覆盖“尚无绑定记录”的并发场景,不修改平台数据库。
|
|
lock := bindingLockPO{SourceDB: key.SourceDB, PlatformBusierID: key.BusierID}
|
|
if err := tx.Clauses(clause.OnConflict{DoNothing: true}).Create(&lock).Error; err != nil {
|
|
return business.ErrStorage
|
|
}
|
|
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("source_db = ? AND platform_busier_id = ?", key.SourceDB, key.BusierID).First(&lock).Error; err != nil {
|
|
return business.ErrStorage
|
|
}
|
|
return fn(context.WithValue(ctx, bindingTxKey{}, tx))
|
|
})
|
|
return storageError(err)
|
|
}
|
|
|
|
func toBizBinding(po bindingPO) *business.Binding {
|
|
return &business.Binding{UserID: po.UserID, PlatformKey: business.PlatformKey{SourceDB: po.SourceDB, BusierID: po.PlatformBusierID}, Account: po.PlatformBusierAccount,
|
|
Status: po.Status, RejectReason: po.RejectReason, CreatedAt: po.CreateTime, ReviewTime: po.ReviewTime, ReviewAccount: po.ReviewAccount}
|
|
}
|
|
func newBinding(b *business.Binding) bindingPO {
|
|
return bindingPO{UserID: b.UserID, SourceDB: b.SourceDB, PlatformBusierID: b.BusierID, PlatformBusierAccount: b.Account, Status: b.Status,
|
|
RejectReason: b.RejectReason, CreateTime: b.CreatedAt, ReviewTime: b.ReviewTime, ReviewAccount: b.ReviewAccount}
|
|
}
|
|
func (r *bindingRepo) ForPlatform(ctx context.Context, key business.PlatformKey) ([]*business.Binding, error) {
|
|
var pos []bindingPO
|
|
if err := r.db(ctx).Where("source_db = ? AND platform_busier_id = ?", key.SourceDB, key.BusierID).Find(&pos).Error; err != nil {
|
|
return nil, business.ErrStorage
|
|
}
|
|
rows := make([]*business.Binding, 0, len(pos))
|
|
for _, po := range pos {
|
|
rows = append(rows, toBizBinding(po))
|
|
}
|
|
return rows, nil
|
|
}
|
|
func (r *bindingRepo) Save(ctx context.Context, b *business.Binding) error {
|
|
po := newBinding(b)
|
|
err := r.db(ctx).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "user_id"}, {Name: "source_db"}, {Name: "platform_busier_id"}},
|
|
DoUpdates: clause.AssignmentColumns([]string{"platform_busier_account", "status", "reject_reason", "create_time", "review_time", "review_account"})}).Create(&po).Error
|
|
if err != nil {
|
|
return business.ErrStorage
|
|
}
|
|
return nil
|
|
}
|
|
func (r *bindingRepo) Delete(ctx context.Context, userID uint, key business.PlatformKey) error {
|
|
result := r.db(ctx).Where("user_id = ? AND source_db = ? AND platform_busier_id = ?", userID, key.SourceDB, key.BusierID).Delete(&bindingPO{})
|
|
if result.Error != nil {
|
|
return business.ErrStorage
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return business.ErrBindingNotFound
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *bindingRepo) List(ctx context.Context, scope business.UserScope, q business.BindingFilter, options ...business.ListOption) ([]*business.Binding, int64, error) {
|
|
db := r.db(ctx).Table("sys_user_bind_platform b").Joins("JOIN sys_users u ON u.id=b.user_id AND u.deleted_at IS NULL")
|
|
db = applyUserScope(db, scope, "u.")
|
|
if q.UserID != 0 {
|
|
db = db.Where("b.user_id = ?", q.UserID)
|
|
}
|
|
if len(q.SourceDBs) > 0 {
|
|
db = db.Where("b.source_db IN ?", q.SourceDBs)
|
|
}
|
|
if q.Account != "" {
|
|
db = db.Where("b.platform_busier_account LIKE ?", "%"+q.Account+"%")
|
|
}
|
|
if q.Status != "" {
|
|
db = db.Where("b.status = ?", q.Status)
|
|
}
|
|
var total int64
|
|
if err := db.Count(&total).Error; err != nil {
|
|
return nil, 0, business.ErrStorage
|
|
}
|
|
o := business.NewListOptions(options...)
|
|
var pos []struct {
|
|
Binding bindingPO `gorm:"embedded"`
|
|
UserName string
|
|
}
|
|
if err := db.Select("b.*,u.username AS user_name").Order("b.create_time DESC").Order("b.source_db,b.platform_busier_id,b.user_id").Offset(o.Offset).Limit(o.Limit).Scan(&pos).Error; err != nil {
|
|
return nil, 0, business.ErrStorage
|
|
}
|
|
rows := make([]*business.Binding, 0, len(pos))
|
|
keys := make(map[business.PlatformKey]bool)
|
|
for _, po := range pos {
|
|
b := toBizBinding(po.Binding)
|
|
zero := int64(0)
|
|
b.PromoteCount = &zero
|
|
b.UserName = po.UserName
|
|
rows = append(rows, b)
|
|
if b.Status == "0" {
|
|
keys[b.PlatformKey] = true
|
|
}
|
|
}
|
|
if len(keys) == 0 {
|
|
return rows, total, nil
|
|
}
|
|
available, err := businessTableAvailable(r.db(ctx), "tab_promote")
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
if !available {
|
|
for _, b := range rows {
|
|
if b.Status == "0" {
|
|
b.PromoteCount = nil
|
|
}
|
|
}
|
|
return rows, total, nil
|
|
}
|
|
query := r.db(ctx).Table("tab_promote").Where("promote_level = ?", 1)
|
|
pairs := r.db(ctx).Session(&gorm.Session{NewDB: true})
|
|
for key := range keys {
|
|
pairs = pairs.Or("(source_db = ? AND busier_id = ?)", key.SourceDB, key.BusierID)
|
|
}
|
|
var counts []struct {
|
|
SourceDB string `gorm:"column:source_db"`
|
|
BusierID uint64
|
|
Total int64
|
|
}
|
|
if err := query.Where(pairs).Select("source_db,busier_id,COUNT(*) AS total").Group("source_db,busier_id").Scan(&counts).Error; err != nil {
|
|
return nil, 0, business.ErrStorage
|
|
}
|
|
byKey := make(map[business.PlatformKey]int64, len(counts))
|
|
for _, c := range counts {
|
|
byKey[business.PlatformKey{SourceDB: c.SourceDB, BusierID: c.BusierID}] = c.Total
|
|
}
|
|
for _, b := range rows {
|
|
if b.Status == "0" {
|
|
count := byKey[b.PlatformKey]
|
|
b.PromoteCount = &count
|
|
}
|
|
}
|
|
return rows, total, nil
|
|
}
|