Files
iotlcm/admin-svr/server/internal/logic/iot/card_channel_assoc.go
T

259 lines
7.5 KiB
Go

package iot
import (
"context"
"fmt"
"strings"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/dao"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/contexts"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
)
const cardChannelAssocTable = "card_channel_assoc"
type cardChannelAssocRecord struct {
Id int64 `orm:"id"`
ChannelKey string `orm:"channel_id"`
MatchType int `orm:"match_type"`
Iccid string `orm:"iccid"`
IccidStart string `orm:"iccid_start"`
IccidEnd string `orm:"iccid_end"`
Status int `orm:"status"`
}
type cardChannelDisplayRecord struct {
ChanKey string
ChanName string
ChanAlias string
TempKey string
}
type cardChannelLookupRecord struct {
Id int64 `orm:"id"`
ChanKey string `orm:"chan_key"`
ChanName string `orm:"chan_name"`
ChanAlias string `orm:"chan_alias"`
TempKey string `orm:"temp_key"`
}
func applyCardChannelAssocFilter(mod *gdb.Model, cardInfoTable string, chanKey string) *gdb.Model {
if mod == nil {
return mod
}
chanKey = strings.TrimSpace(chanKey)
if chanKey == "" {
return mod
}
return mod.Where(cardChannelAssocExistsSQL(cardInfoTable), chanKey)
}
func cardChannelAssocExistsSQL(cardInfoTable string) string {
cardInfoTable = strings.TrimSpace(cardInfoTable)
if cardInfoTable == "" {
cardInfoTable = dao.TSimCardInfo.Table()
}
channelTable := dao.TSimChannels.Table()
cardColumns := dao.TSimCardInfo.Columns()
channelColumns := dao.TSimChannels.Columns()
return fmt.Sprintf(
"EXISTS (SELECT 1 FROM `%s` a LEFT JOIN `%s` c ON c.`%s` = a.`channel_id` WHERE a.`status` = 1 AND c.`%s` = `%s`.`%s` AND c.`%s` = ? AND ((a.`match_type` = 1 AND a.`iccid` COLLATE utf8mb4_general_ci = `%s`.`%s`) OR (a.`match_type` = 2 AND a.`iccid_start` COLLATE utf8mb4_general_ci <= `%s`.`%s` AND a.`iccid_end` COLLATE utf8mb4_general_ci >= `%s`.`%s`)))",
cardChannelAssocTable,
channelTable,
channelColumns.ChanKey,
channelColumns.TenantId,
cardInfoTable,
cardColumns.TenantId,
channelColumns.ChanKey,
cardInfoTable,
cardColumns.Iccid,
cardInfoTable,
cardColumns.Iccid,
cardInfoTable,
cardColumns.Iccid,
)
}
func enrichCardChannelList(ctx context.Context, list []*model.TSimCardInfoListModel) error {
if len(list) == 0 {
return nil
}
channelCache := make(map[string]cardChannelDisplayRecord)
for _, item := range list {
if item == nil {
continue
}
display, ok, err := resolveCardChannelDisplayByIccid(ctx, item.Iccid, channelCache)
if err != nil {
return err
}
if !ok {
continue
}
item.ChanKey = display.ChanKey
item.ChanName = display.ChanName
item.ChanAlias = display.ChanAlias
}
return nil
}
func enrichCardChannelView(ctx context.Context, item *model.TSimCardInfoViewModel) error {
if item == nil {
return nil
}
display, ok, err := resolveCardChannelDisplayByIccid(ctx, item.Iccid, nil)
if err != nil {
return err
}
if !ok {
return nil
}
item.ChanKey = display.ChanKey
item.ChanName = display.ChanName
item.ChanAlias = display.ChanAlias
return nil
}
func enrichSimKeyChannelFromAssoc(ctx context.Context, simKey *model.SimKey) error {
if simKey == nil {
return nil
}
display, ok, err := resolveCardChannelDisplayByIccid(ctx, simKey.ICCID, nil)
if err != nil {
return err
}
if ok && strings.TrimSpace(display.ChanKey) != "" {
simKey.ChanKey = display.ChanKey
}
return nil
}
func resolveCardChannelDisplayByIccid(ctx context.Context, iccid string, channelCache map[string]cardChannelDisplayRecord) (cardChannelDisplayRecord, bool, error) {
assoc, err := resolveCardChannelAssocByIccid(ctx, iccid)
if err != nil || assoc == nil {
return cardChannelDisplayRecord{}, false, err
}
return resolveCardChannelDisplayByAssoc(ctx, assoc, channelCache)
}
func resolveCardChannelDisplayByAssoc(ctx context.Context, assoc *cardChannelAssocRecord, channelCache map[string]cardChannelDisplayRecord) (cardChannelDisplayRecord, bool, error) {
if assoc == nil {
return cardChannelDisplayRecord{}, false, nil
}
return resolveCardChannelDisplayByChannelKey(ctx, assoc.ChannelKey, channelCache)
}
func resolveCardChannelAssocByIccid(ctx context.Context, iccid string) (*cardChannelAssocRecord, error) {
iccid = strings.TrimSpace(iccid)
if iccid == "" {
return nil, nil
}
var exact *cardChannelAssocRecord
if err := g.DB().Ctx(ctx).Model(cardChannelAssocTable).
Fields("id", "channel_id", "match_type", "iccid", "iccid_start", "iccid_end", "status").
Where("status", 1).
Where("match_type", 1).
Where("iccid COLLATE utf8mb4_general_ci = ?", iccid).
OrderDesc("id").
Limit(1).
Scan(&exact); err != nil {
return nil, gerror.Wrap(err, "查询卡通道单卡关联失败")
}
if exact != nil && strings.TrimSpace(exact.ChannelKey) != "" {
return exact, nil
}
var ranged *cardChannelAssocRecord
if err := g.DB().Ctx(ctx).Model(cardChannelAssocTable).
Fields("id", "channel_id", "match_type", "iccid", "iccid_start", "iccid_end", "status").
Where("status", 1).
Where("match_type", 2).
Where("iccid_start COLLATE utf8mb4_general_ci <= ? AND iccid_end COLLATE utf8mb4_general_ci >= ?", iccid, iccid).
OrderDesc("id").
Limit(1).
Scan(&ranged); err != nil {
return nil, gerror.Wrap(err, "查询卡通道号段关联失败")
}
if ranged != nil && strings.TrimSpace(ranged.ChannelKey) != "" {
return ranged, nil
}
return nil, nil
}
func resolveCardChannelDisplayByChannelKey(ctx context.Context, chanKey string, channelCache map[string]cardChannelDisplayRecord) (cardChannelDisplayRecord, bool, error) {
chanKey = strings.TrimSpace(chanKey)
if chanKey == "" {
return cardChannelDisplayRecord{}, false, nil
}
if channelCache != nil {
if cached, ok := channelCache[chanKey]; ok {
return cached, true, nil
}
}
channel, err := loadCardChannelByKey(ctx, chanKey)
if err != nil {
return cardChannelDisplayRecord{}, false, err
}
if channel == nil {
return cardChannelDisplayRecord{}, false, nil
}
display := cardChannelDisplayRecord{
ChanKey: strings.TrimSpace(channel.ChanKey),
ChanName: strings.TrimSpace(channel.ChanName),
ChanAlias: strings.TrimSpace(channel.ChanAlias),
TempKey: strings.TrimSpace(channel.TempKey),
}
if channelCache != nil {
channelCache[chanKey] = display
}
return display, true, nil
}
func loadCardChannelByKey(ctx context.Context, chanKey string) (*cardChannelLookupRecord, error) {
chanKey = strings.TrimSpace(chanKey)
if chanKey == "" {
return nil, nil
}
var channel *cardChannelLookupRecord
columns := dao.TSimChannels.Columns()
if err := cardChannelLookupModel(ctx).
Where(columns.ChanKey, chanKey).
Limit(1).
Scan(&channel); err != nil {
return nil, gerror.Wrap(err, "查询通道信息失败")
}
if channel != nil && strings.TrimSpace(channel.ChanKey) != "" {
return channel, nil
}
channel = nil
if err := dao.TSimChannels.Ctx(ctx).
Fields(columns.Id, columns.ChanKey, columns.ChanName, columns.ChanAlias, columns.TempKey).
Where(columns.ChanKey, chanKey).
Limit(1).
Scan(&channel); err != nil {
return nil, gerror.Wrap(err, "查询通道信息失败")
}
return channel, nil
}
func cardChannelLookupModel(ctx context.Context) *gdb.Model {
columns := dao.TSimChannels.Columns()
return dao.TSimChannels.Ctx(ctx).
Fields(columns.Id, columns.ChanKey, columns.ChanName, columns.ChanAlias, columns.TempKey).
Where(columns.TenantId, contexts.GetTenantId(ctx))
}
func logCardChannelDisplayResolverError(ctx context.Context, err error) {
if err != nil {
g.Log().Warningf(ctx, "load card channel display failed: %v", err)
}
}