92 lines
2.8 KiB
Go
92 lines
2.8 KiB
Go
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)
|
|
}
|