213 lines
7.2 KiB
Go
213 lines
7.2 KiB
Go
package simwarning
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/consts"
|
|
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/dao"
|
|
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model"
|
|
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model/do"
|
|
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/service"
|
|
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
|
"github.com/gogf/gf/v2/frame/g"
|
|
)
|
|
|
|
const (
|
|
warnActionDataCut = "data_cut"
|
|
warnDataServiceStatusEnabled = 1
|
|
warnDataServiceStatusDisabled = 0
|
|
)
|
|
|
|
func (s *sSimWarning) handleAutoAction(ctx context.Context, hit warningHit, warnLogID int64, runTime time.Time) (bool, error) {
|
|
if !autoDataCutEnabled(hit) {
|
|
return false, nil
|
|
}
|
|
allowed, reason := autoDataCutEligibility(hit)
|
|
if !allowed {
|
|
g.Log().Infof(ctx, "SimWarning auto data cut skipped, reason:%s, configId:%d, cardId:%d, warnLogId:%d", reason, hit.Config.Id, hit.Card.Id, warnLogID)
|
|
return false, nil
|
|
}
|
|
|
|
acquired, actionKey, err := acquireWarningActionDedupe(ctx, hit, warnActionDataCut, runTime)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if !acquired {
|
|
g.Log().Infof(ctx, "SimWarning auto data cut duplicated, action:%s, configId:%d, cardId:%d, warnLogId:%d", warnActionDataCut, hit.Config.Id, hit.Card.Id, warnLogID)
|
|
return false, nil
|
|
}
|
|
|
|
eligible, reason, err := s.ensureDataCutEligible(ctx, hit)
|
|
if err != nil {
|
|
releaseWarningDedupe(ctx, actionKey)
|
|
return false, err
|
|
}
|
|
if !eligible {
|
|
releaseWarningDedupe(ctx, actionKey)
|
|
g.Log().Infof(ctx, "SimWarning auto data cut skipped, reason:%s, configId:%d, cardId:%d, warnLogId:%d", reason, hit.Config.Id, hit.Card.Id, warnLogID)
|
|
return false, nil
|
|
}
|
|
|
|
orderNum, err := s.disableCardDataService(ctx, hit)
|
|
if err != nil {
|
|
releaseWarningDedupe(ctx, actionKey)
|
|
return false, err
|
|
}
|
|
|
|
g.Log().Infof(ctx, "SimWarning auto data cut success, action:%s, configId:%d, cardId:%d, warnLogId:%d, orderNum:%s", warnActionDataCut, hit.Config.Id, hit.Card.Id, warnLogID, orderNum)
|
|
return true, nil
|
|
}
|
|
|
|
func autoDataCutEnabled(hit warningHit) bool {
|
|
return hit.Config.ItemType == warnItemTypeCard &&
|
|
(isExpireKind(hit.Kind) || isTrafficKind(hit.Kind)) &&
|
|
hit.WarnStage == warnStageThird &&
|
|
hit.Config.AutoAction == warnAutoActionDataCut
|
|
}
|
|
|
|
func autoDataCutEligibility(hit warningHit) (bool, string) {
|
|
if hit.Card.BossCardStatus == consts.V3ApiSimBossCardStatusStopped {
|
|
return false, "\u5361\u5df2\u505c\u673a\uff0c\u81ea\u52a8\u65ad\u7f51\u672a\u6267\u884c"
|
|
}
|
|
if hit.Card.BossCardStatus != consts.V3ApiSimBossCardStatusActivated {
|
|
return false, "\u5f53\u524d\u8fd0\u8425\u5546\u72b6\u6001\u4e3a" + bossCardStatusText(hit.Card.BossCardStatus) + "\uff0c\u4ec5\u5df2\u6fc0\u6d3b\u5361\u53ef\u4ee5\u81ea\u52a8\u65ad\u7f51"
|
|
}
|
|
if hit.Card.DataServiceStatus == warnDataServiceStatusDisabled {
|
|
return false, "\u6570\u636e\u670d\u52a1\u5df2\u505c\u7528\uff0c\u81ea\u52a8\u65ad\u7f51\u672a\u6267\u884c"
|
|
}
|
|
if hit.Card.DataServiceStatus != warnDataServiceStatusEnabled {
|
|
return false, "\u6570\u636e\u670d\u52a1\u72b6\u6001\u65e0\u6548\uff0c\u81ea\u52a8\u65ad\u7f51\u672a\u6267\u884c"
|
|
}
|
|
if strings.TrimSpace(hit.Card.ChanKey) == "" {
|
|
return false, "\u5361\u7f3a\u5c11\u901a\u9053\u6807\u8bc6\uff0c\u81ea\u52a8\u65ad\u7f51\u672a\u6267\u884c"
|
|
}
|
|
if strings.TrimSpace(hit.Card.Iccid) == "" &&
|
|
strings.TrimSpace(hit.Card.Msisdn) == "" &&
|
|
strings.TrimSpace(hit.Card.Imsi) == "" {
|
|
return false, "\u5361\u7f3a\u5c11 ICCID/MSISDN/IMSI\uff0c\u81ea\u52a8\u65ad\u7f51\u672a\u6267\u884c"
|
|
}
|
|
return true, "\u5df2\u914d\u7f6e\u7b2c\u4e09\u6863\u65ad\u7f51\uff0c\u7cfb\u7edf\u5c06\u5728\u72b6\u6001\u6821\u9a8c\u901a\u8fc7\u540e\u53d1\u8d77\u6570\u636e\u670d\u52a1\u505c\u7528"
|
|
}
|
|
|
|
func (s *sSimWarning) ensureDataCutEligible(ctx context.Context, hit warningHit) (bool, string, error) {
|
|
simKey, err := dataCutSimKey(hit)
|
|
if err != nil {
|
|
return false, "", err
|
|
}
|
|
output, err := service.UpstreamChan().QuerySimCardStatus(ctx, &model.SimCardStatusInput{
|
|
SimKeys: []*model.SimKey{simKey},
|
|
})
|
|
if err != nil {
|
|
return false, "", err
|
|
}
|
|
if len(output) == 0 {
|
|
return false, "", gerror.New("upstream card status is empty")
|
|
}
|
|
status := output[0].ResData.CardStatus
|
|
if status == consts.V3ApiSimBossCardStatusStopped {
|
|
return false, "\u4e0a\u6e38\u5361\u5df2\u505c\u673a\uff0c\u81ea\u52a8\u65ad\u7f51\u672a\u6267\u884c", nil
|
|
}
|
|
if status != consts.V3ApiSimBossCardStatusActivated {
|
|
return false, fmt.Sprintf("\u4e0a\u6e38\u5f53\u524d\u72b6\u6001\u4e3a%s\uff0c\u4ec5\u5df2\u6fc0\u6d3b\u5361\u53ef\u4ee5\u81ea\u52a8\u65ad\u7f51", bossCardStatusText(status)), nil
|
|
}
|
|
return true, "\u4e0a\u6e38\u72b6\u6001\u5df2\u786e\u8ba4\uff0c\u53ef\u6267\u884c\u6570\u636e\u670d\u52a1\u505c\u7528", nil
|
|
}
|
|
|
|
func bossCardStatusText(status int) string {
|
|
if name := consts.V3ApiSimBossCardStatusNameMap[status]; name != "" {
|
|
return name
|
|
}
|
|
return "\u672a\u77e5\u72b6\u6001"
|
|
}
|
|
|
|
func (s *sSimWarning) disableCardDataService(ctx context.Context, hit warningHit) (string, error) {
|
|
simKey, err := dataCutSimKey(hit)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
output, err := service.UpstreamChan().ChangeSimApnFunction(ctx, &model.SimCardOperateChangeApnInput{
|
|
SimKeys: []*model.SimKey{simKey},
|
|
ReqData: model.SimCardOperateChangeApnInputItem{
|
|
OperType: strconv.Itoa(consts.SimCardDataOperTypeStop),
|
|
ApnName: consts.SimCardDataApnName,
|
|
},
|
|
})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(output) == 0 {
|
|
return "", gerror.New("upstream data service stop response is empty")
|
|
}
|
|
item := output[0]
|
|
if item.Code != 0 {
|
|
message := strings.TrimSpace(item.Message)
|
|
if message == "" {
|
|
message = "upstream data service stop failed"
|
|
}
|
|
return "", gerror.New(message)
|
|
}
|
|
if err = s.updateLocalDataServiceDisabled(ctx, hit); err != nil {
|
|
return item.ResData.OrderNum, err
|
|
}
|
|
return item.ResData.OrderNum, nil
|
|
}
|
|
|
|
func dataCutSimKey(hit warningHit) (*model.SimKey, error) {
|
|
chanKey := strings.TrimSpace(hit.Card.ChanKey)
|
|
if chanKey == "" {
|
|
return nil, gerror.New("card chan key is empty")
|
|
}
|
|
if strings.TrimSpace(hit.Card.Iccid) == "" &&
|
|
strings.TrimSpace(hit.Card.Msisdn) == "" &&
|
|
strings.TrimSpace(hit.Card.Imsi) == "" {
|
|
return nil, gerror.New("card identity is empty")
|
|
}
|
|
return &model.SimKey{
|
|
ChanKey: chanKey,
|
|
ICCID: strings.TrimSpace(hit.Card.Iccid),
|
|
MSISDN: strings.TrimSpace(hit.Card.Msisdn),
|
|
IMSI: strings.TrimSpace(hit.Card.Imsi),
|
|
}, nil
|
|
}
|
|
|
|
func (s *sSimWarning) updateLocalDataServiceDisabled(ctx context.Context, hit warningHit) error {
|
|
columns := dao.TSimCardInfo.Columns()
|
|
result, err := dao.TSimCardInfo.Ctx(ctx).
|
|
Where(columns.Id, hit.Card.Id).
|
|
Where(columns.TenantId, hit.Config.TenantId).
|
|
Where(columns.DataServiceStatus, warnDataServiceStatusEnabled).
|
|
Data(do.TSimCardInfo{
|
|
DataServiceStatus: warnDataServiceStatusDisabled,
|
|
UpdatedBy: hit.Config.CreatedBy,
|
|
}).
|
|
Update()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
affected, err := result.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if affected == 1 {
|
|
return nil
|
|
}
|
|
|
|
count, err := dao.TSimCardInfo.Ctx(ctx).
|
|
Where(columns.Id, hit.Card.Id).
|
|
Where(columns.TenantId, hit.Config.TenantId).
|
|
Where(columns.DataServiceStatus, warnDataServiceStatusDisabled).
|
|
Count()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if count > 0 {
|
|
return nil
|
|
}
|
|
return gerror.New("local data service status changed before update")
|
|
}
|