feat: integrate OA activation workflows and business migration

This commit is contained in:
Yvan
2026-11-07 00:09:19 +08:00
parent 64aca495f2
commit 9caf5b1abc
47 changed files with 1831 additions and 152 deletions
+33 -31
View File
@@ -55,10 +55,13 @@ func toBizAlertExemption(p alertExemptionPO) *business.AlertExemption {
return &business.AlertExemption{ID: p.ID, ChannelKey: business.ChannelKey{SourceDB: p.SourceDB, ID: p.PromoteID}, ChannelName: p.ChannelName, OwnerID: p.OwnerID, AddedBy: p.AddedBy, AddedName: p.AddedName, Reason: p.Reason, AddedAt: p.AddedAt, RemovedBy: p.RemovedBy, RemovedName: p.RemovedName, RemoveReason: p.RemoveReason, RemovedAt: p.RemovedAt}
}
type alertGovernanceRepo struct{ data Provider }
type alertGovernanceRepo struct {
data Provider
databases PlatformProvider
}
func NewAlertGovernanceRepo(data Provider) business.AlertGovernanceRepo {
return &alertGovernanceRepo{data}
func NewAlertGovernanceRepo(data Provider, databases PlatformProvider) business.AlertGovernanceRepo {
return &alertGovernanceRepo{data: data, databases: databases}
}
func (r *alertGovernanceRepo) Candidates(ctx context.Context, scope business.UserScope, keyword string, limit int) ([]*business.AlertChannelOption, error) {
@@ -196,47 +199,46 @@ func alertLostQuery(db *gorm.DB, sourceColumn, idColumn string, window business.
return db.Table("tab_promote lp").Select("1").Where("lp.source_db="+sourceColumn+" AND lp.id="+idColumn).
Where("(COALESCE(NULLIF(lp.last_login_time,0),lp.create_time)>0 AND COALESCE(NULLIF(lp.last_login_time,0),lp.create_time)<?) OR (?) < CAST(? AS DECIMAL(20,2))", window.LoginBefore, pay, window.MinPay)
}
func (r *alertGovernanceRepo) LostExemptions(ctx context.Context, window business.AlertLossWindow) ([]*business.AlertExemption, error) {
// 清理依据 OA 实际入池记录;不能仅因本地流水低而绕过 OA 的豁免和跨平台判定。
func (r *alertGovernanceRepo) LostExemptions(ctx context.Context, _ business.AlertLossWindow) ([]*business.AlertExemption, error) {
db := r.data.DB().WithContext(ctx)
var pos []alertExemptionPO
// 没有在名单渠道时无需读取平台明细。
if err := db.Select("id").Where("removed_at IS NULL").Limit(1).Find(&pos).Error; err != nil {
var entries []alertExemptionPO
if err := db.Where("removed_at IS NULL").Find(&entries).Error; err != nil {
return nil, business.ErrStorage
}
if len(pos) == 0 {
if len(entries) == 0 {
return nil, nil
}
available, err := businessTablesAvailable(db, "tab_promote", "tab_spend")
if err != nil {
return nil, err
oa, err := r.databases.Database("oa")
if err != nil || oa == nil {
return nil, business.ErrActivationSource
}
if !available {
return nil, business.ErrAlertChannelsUnavailable
oa = oa.WithContext(ctx)
ok, err := businessTableAvailable(oa, "sys_platform_promote_active_pool")
if err != nil || !ok {
return nil, business.ErrActivationSource
}
result := []*business.AlertExemption{}
var cursor uint64
for {
var batch []alertExemptionPO
if err := db.Where("removed_at IS NULL AND id>?", cursor).Order("id").Limit(500).Find(&batch).Error; err != nil {
return nil, business.ErrStorage
for start := 0; start < len(entries); start += 500 {
batch := entries[start:min(start+500, len(entries))]
pairs := [][]any{}
for _, e := range batch {
pairs = append(pairs, []any{e.SourceDB, e.PromoteID})
}
if len(batch) == 0 {
break
var pools []activationPoolPO
if err := oa.Where("(platform_name,promote_id) IN ?", pairs).Find(&pools).Error; err != nil {
return nil, business.ErrActivationSource
}
keys := make([]business.ChannelKey, 0, len(batch))
for _, p := range batch {
keys = append(keys, business.ChannelKey{SourceDB: p.SourceDB, ID: p.PromoteID})
byKey := map[business.ChannelKey]activationPoolPO{}
for _, p := range pools {
byKey[business.ChannelKey{SourceDB: p.PlatformName, ID: p.PromoteID}] = p
}
states, err := loadAlertLoss(db, keys, window)
if err != nil {
return nil, err
}
for _, p := range batch {
if lost := states[business.ChannelKey{SourceDB: p.SourceDB, ID: p.PromoteID}]; lost != nil && *lost {
result = append(result, toBizAlertExemption(p))
for _, e := range batch {
if p, ok := byKey[business.ChannelKey{SourceDB: e.SourceDB, ID: e.PromoteID}]; ok && (p.DeletedAt == nil || !p.CreatedAt.Before(e.AddedAt)) {
result = append(result, toBizAlertExemption(e))
}
}
cursor = batch[len(batch)-1].ID
}
return result, nil
}