feat: 添加独立其他设置菜单及有效端参数保存
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
package business
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
"kra/internal/biz/business"
|
||||
)
|
||||
|
||||
const otherSettingsKey = "sw.channel_effectiveness"
|
||||
|
||||
// Projection of the existing parameter-management table; no new settings table.
|
||||
type otherSettingsPO struct {
|
||||
ID uint `gorm:"primaryKey"`
|
||||
CreatedAt, UpdatedAt time.Time
|
||||
DeletedAt gorm.DeletedAt
|
||||
Name, Key, Value, Desc string
|
||||
}
|
||||
|
||||
func (otherSettingsPO) TableName() string { return "sys_params" }
|
||||
|
||||
type effectivenessJSON struct {
|
||||
Amount *int64 `json:"amount"`
|
||||
Days *int64 `json:"days"`
|
||||
}
|
||||
|
||||
func newOtherSettings(value business.OtherSettings) otherSettingsPO {
|
||||
encoded, _ := json.Marshal(effectivenessJSON{Amount: &value.Amount, Days: &value.Days})
|
||||
return otherSettingsPO{Name: "渠道有效端判定", Key: otherSettingsKey, Value: string(encoded), Desc: "其他设置:达标金额(元)和判定窗口(天)"}
|
||||
}
|
||||
|
||||
func toBizOtherSettings(po otherSettingsPO) (*business.OtherSettings, error) {
|
||||
var value effectivenessJSON
|
||||
if err := json.Unmarshal([]byte(po.Value), &value); err != nil || value.Amount == nil || value.Days == nil {
|
||||
return nil, business.ErrOtherSettingsStored
|
||||
}
|
||||
result := &business.OtherSettings{Amount: *value.Amount, Days: *value.Days, UpdatedAt: po.UpdatedAt}
|
||||
if err := business.ValidateOtherSettings(*result); err != nil {
|
||||
return nil, business.ErrOtherSettingsStored
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
type otherSettingsRepo struct {
|
||||
data Provider
|
||||
// Serialize first creation as sys_params has no unique index on key.
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func NewOtherSettingsRepo(data Provider) business.OtherSettingsRepo {
|
||||
return &otherSettingsRepo{data: data}
|
||||
}
|
||||
|
||||
func (r *otherSettingsRepo) Find(ctx context.Context) (*business.OtherSettings, error) {
|
||||
var po otherSettingsPO
|
||||
err := r.data.DB().WithContext(ctx).Where(map[string]any{"key": otherSettingsKey}).First(&po).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, business.ErrStorage
|
||||
}
|
||||
return toBizOtherSettings(po)
|
||||
}
|
||||
|
||||
func (r *otherSettingsRepo) Save(ctx context.Context, value business.OtherSettings) (*business.OtherSettings, error) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
po := newOtherSettings(value)
|
||||
err := r.data.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
var existing otherSettingsPO
|
||||
err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where(map[string]any{"key": otherSettingsKey}).First(&existing).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return tx.Create(&po).Error
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
po.ID, po.CreatedAt, po.UpdatedAt = existing.ID, existing.CreatedAt, time.Now()
|
||||
return tx.Model(&existing).Updates(map[string]any{"value": po.Value, "updated_at": po.UpdatedAt}).Error
|
||||
})
|
||||
if err != nil {
|
||||
return nil, business.ErrStorage
|
||||
}
|
||||
return toBizOtherSettings(po)
|
||||
}
|
||||
Reference in New Issue
Block a user