feat(sms): 新增节点短信提醒(审核未通过/被租用需辅助/上架未成交)
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
package sms
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ConfigKey 主站节点短信配置项,与分销站点的 business_templates 同构。
|
||||
const ConfigKey = "sms.business_templates"
|
||||
|
||||
// DefaultStaleDays 上架未成交提醒的默认天数阈值。
|
||||
const DefaultStaleDays = 3
|
||||
|
||||
// ConfigReader 读取系统配置文本,由 systemconfig.Repository 实现。
|
||||
type ConfigReader interface {
|
||||
FindValue(ctx context.Context, key string) (string, error)
|
||||
}
|
||||
|
||||
// LoadConfig 从系统配置读取并解析节点短信配置。
|
||||
func LoadConfig(ctx context.Context, reader ConfigReader) (Config, error) {
|
||||
if reader == nil {
|
||||
return DefaultConfig(), nil
|
||||
}
|
||||
value, err := reader.FindValue(ctx, ConfigKey)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
return ParseConfigValue(value)
|
||||
}
|
||||
|
||||
// NodeConfig 是单个节点的开关与模板 CODE。
|
||||
type NodeConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
TemplateCode string `json:"template_code"`
|
||||
// StaleDays 仅上架未成交提醒使用:上架满多少天仍未成交才提醒,0 表示取默认值。
|
||||
StaleDays int `json:"stale_days,omitempty"`
|
||||
}
|
||||
|
||||
// Config 是主站节点短信配置(系统配置 sms.business_templates 的 JSON 结构)。
|
||||
type Config struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Nodes map[string]NodeConfig `json:"nodes"`
|
||||
}
|
||||
|
||||
// DefaultConfig 返回默认配置:总开关关闭(避免误发产生短信费用),
|
||||
// 三个节点默认各自开启,模板 CODE 留空由运营在后台填写。
|
||||
func DefaultConfig() Config {
|
||||
nodes := make(map[string]NodeConfig, len(nodeMetas))
|
||||
for _, meta := range nodeMetas {
|
||||
node := NodeConfig{Enabled: true}
|
||||
if meta.SupportsStaleDays {
|
||||
node.StaleDays = DefaultStaleDays
|
||||
}
|
||||
nodes[meta.Code] = node
|
||||
}
|
||||
return Config{Enabled: false, Nodes: nodes}
|
||||
}
|
||||
|
||||
// DefaultConfigValue 返回默认配置的 JSON 文本。
|
||||
func DefaultConfigValue() string {
|
||||
raw, err := MarshalConfig(DefaultConfig())
|
||||
if err != nil {
|
||||
return `{"enabled":false,"nodes":{}}`
|
||||
}
|
||||
return raw
|
||||
}
|
||||
|
||||
// ParseConfigValue 解析系统配置里的 JSON 文本,缺失字段回落到默认值。
|
||||
func ParseConfigValue(value string) (Config, error) {
|
||||
cfg := DefaultConfig()
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" {
|
||||
return cfg, nil
|
||||
}
|
||||
var raw struct {
|
||||
Enabled *bool `json:"enabled"`
|
||||
Nodes map[string]NodeConfig `json:"nodes"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(value), &raw); err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
if raw.Enabled != nil {
|
||||
cfg.Enabled = *raw.Enabled
|
||||
}
|
||||
if raw.Nodes != nil {
|
||||
// 以已登记节点为基准合并,避免后台配置里出现未知节点。
|
||||
for code, node := range raw.Nodes {
|
||||
if !IsKnownNode(code) {
|
||||
continue
|
||||
}
|
||||
node.TemplateCode = strings.TrimSpace(node.TemplateCode)
|
||||
if node.StaleDays < 0 {
|
||||
node.StaleDays = 0
|
||||
}
|
||||
cfg.Nodes[code] = node
|
||||
}
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// MarshalConfig 规范化并序列化配置。
|
||||
func MarshalConfig(cfg Config) (string, error) {
|
||||
normalized := DefaultConfig()
|
||||
normalized.Enabled = cfg.Enabled
|
||||
for code, node := range cfg.Nodes {
|
||||
if !IsKnownNode(code) {
|
||||
continue
|
||||
}
|
||||
node.TemplateCode = strings.TrimSpace(node.TemplateCode)
|
||||
if node.StaleDays < 0 {
|
||||
node.StaleDays = 0
|
||||
}
|
||||
normalized.Nodes[code] = node
|
||||
}
|
||||
raw, err := json.Marshal(normalized)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(raw), nil
|
||||
}
|
||||
|
||||
// Node 返回指定节点的配置。
|
||||
func (c Config) Node(code string) (NodeConfig, bool) {
|
||||
node, ok := c.Nodes[code]
|
||||
return node, ok
|
||||
}
|
||||
|
||||
// NodeActive 判断节点是否可发送:总开关、节点开关与模板 CODE 都必须就绪。
|
||||
func (c Config) NodeActive(code string) bool {
|
||||
if !c.Enabled {
|
||||
return false
|
||||
}
|
||||
node, ok := c.Node(code)
|
||||
if !ok || !node.Enabled {
|
||||
return false
|
||||
}
|
||||
return strings.TrimSpace(node.TemplateCode) != ""
|
||||
}
|
||||
|
||||
// StaleDaysFor 返回上架未成交提醒的天数阈值,未配置时取默认值。
|
||||
func (c Config) StaleDaysFor(code string) int {
|
||||
node, ok := c.Node(code)
|
||||
if !ok || node.StaleDays <= 0 {
|
||||
return DefaultStaleDays
|
||||
}
|
||||
return node.StaleDays
|
||||
}
|
||||
Reference in New Issue
Block a user