package app import ( "context" "strings" "git.5iot.com/iotlcm-public/iotlcm-app/internal/dao" "git.5iot.com/iotlcm-public/iotlcm-app/internal/library/contexts" "git.5iot.com/iotlcm-public/iotlcm-app/internal/model/entity" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" ) type appCardChannelInfo struct { ChanKey string ChanName string ChanAlias string TempKey string ChanStatus int } func (s *sAppCard) findDiagnosisAssocChannel(ctx context.Context, tenantId string, iccid string) (*appCardChannelInfo, error) { iccid = strings.TrimSpace(iccid) if iccid == "" { return nil, nil } var assoc *struct { ChannelKey string `orm:"channel_id"` } base := g.DB().Model("card_channel_assoc").Ctx(ctx).Fields("channel_id").Where("status", 1) var err error err = base.Clone().Where("match_type", 1).Where("iccid COLLATE utf8mb4_general_ci = ?", iccid). OrderDesc("id").Limit(1).Scan(&assoc) if err != nil { return nil, gerror.Wrap(err, "查询卡通道单卡关联失败") } if assoc == nil || strings.TrimSpace(assoc.ChannelKey) == "" { err = base.Clone().Where("match_type", 2). Where("iccid_start COLLATE utf8mb4_general_ci <= ?", iccid). Where("iccid_end COLLATE utf8mb4_general_ci >= ?", iccid). OrderDesc("id").Limit(1).Scan(&assoc) if err != nil { return nil, gerror.Wrap(err, "查询卡通道号段关联失败") } } if assoc == nil || strings.TrimSpace(assoc.ChannelKey) == "" { return nil, nil } if tenantId = strings.TrimSpace(tenantId); tenantId == "" { tenantId = contexts.GetTenantId(ctx) } channel, err := s.findCardChannelEntityByKey(ctx, tenantId, assoc.ChannelKey) if err != nil || channel != nil || tenantId == "" { return appCardChannelInfoFromEntity(channel), err } channel, err = s.findCardChannelEntityByKey(ctx, "", assoc.ChannelKey) return appCardChannelInfoFromEntity(channel), err } func (s *sAppCard) attachCardChannelInfo(ctx context.Context, row *appCardQueryRow) error { if row == nil { return nil } info, err := s.loadCardChannelInfo(ctx, row.TenantId, row.Iccid, row.ChanKey) if err != nil { return err } if info == nil { return nil } row.ChanKey = info.ChanKey row.ChanName = info.ChanName row.ChanAlias = info.ChanAlias row.TempKey = info.TempKey return nil } func (s *sAppCard) attachDiagnosisCardChannelInfo(ctx context.Context, row *appCardQueryRow) error { if row == nil { return nil } info, err := s.loadDiagnosisCardChannelInfo(ctx, row.TenantId, row.Iccid, row.ChanKey) if err != nil { return err } if info == nil { return nil } row.ChanKey = info.ChanKey row.ChanName = info.ChanName row.ChanAlias = info.ChanAlias row.TempKey = info.TempKey return nil } func (s *sAppCard) attachCardChannelInfoRows(ctx context.Context, rows []*appCardQueryRow) error { if len(rows) == 0 { return nil } cache := make(map[string]*appCardChannelInfo, len(rows)) for _, row := range rows { if row == nil { continue } cacheKey := strings.Join([]string{ strings.TrimSpace(row.TenantId), strings.TrimSpace(row.Iccid), strings.TrimSpace(row.ChanKey), }, "|") info, ok := cache[cacheKey] if !ok { var err error info, err = s.loadCardChannelInfo(ctx, row.TenantId, row.Iccid, row.ChanKey) if err != nil { return err } cache[cacheKey] = info } if info == nil { continue } row.ChanKey = info.ChanKey row.ChanName = info.ChanName row.ChanAlias = info.ChanAlias row.TempKey = info.TempKey } return nil } func (s *sAppCard) loadCardChannelInfo(ctx context.Context, tenantId string, iccid string, legacyChanKey string) (*appCardChannelInfo, error) { tenantId = strings.TrimSpace(tenantId) legacyChanKey = strings.TrimSpace(legacyChanKey) if legacyChanKey == "" { return nil, nil } return s.findLegacyCardChannelInfo(ctx, tenantId, legacyChanKey) } func (s *sAppCard) loadDiagnosisCardChannelInfo(ctx context.Context, tenantId string, iccid string, legacyChanKey string) (*appCardChannelInfo, error) { card, err := queryLegacyDiagnosisCard(ctx, iccid) if err != nil || card == nil { return nil, err } return s.findLegacyCardChannelInfo(ctx, tenantId, card.ChannelKey) } // resolveLifecycleCardChannelInfo resolves a writable card operation channel. // Card ownership still comes from the current platform; the legacy database is // only a read-only fallback for the channel code. func (s *sAppCard) resolveLifecycleCardChannelInfo(ctx context.Context, tenantId string, iccid string, currentChanKey string) (*appCardChannelInfo, error) { currentChanKey = strings.TrimSpace(currentChanKey) if currentChanKey != "" { info, err := s.findLegacyCardChannelInfo(ctx, tenantId, currentChanKey) if err != nil { return nil, err } if appCardChannelAvailable(info) { return info, nil } } card, err := queryLegacyDiagnosisCard(ctx, strings.TrimSpace(iccid)) if err != nil || card == nil || strings.TrimSpace(card.ICCID) != strings.TrimSpace(iccid) { return nil, err } info, err := s.findLegacyCardChannelInfo(ctx, tenantId, card.ChannelKey) if err != nil { return nil, err } if !appCardChannelAvailable(info) { return nil, nil } return info, nil } func appCardChannelAvailable(info *appCardChannelInfo) bool { return info != nil && strings.TrimSpace(info.ChanKey) != "" && info.ChanStatus == 0 } func (s *sAppCard) findLegacyCardChannelInfo(ctx context.Context, tenantId string, chanKey string) (*appCardChannelInfo, error) { chanKey = strings.TrimSpace(chanKey) if chanKey == "" { return nil, nil } if tenantId = strings.TrimSpace(tenantId); tenantId == "" { tenantId = contexts.GetTenantId(ctx) } if tenantId != "" { channel, err := s.findCardChannelEntityByKey(ctx, tenantId, chanKey) if err != nil || channel != nil { return appCardChannelInfoFromEntity(channel), err } } channel, err := s.findCardChannelEntityByKey(ctx, "", chanKey) return appCardChannelInfoFromEntity(channel), err } func (s *sAppCard) findCardChannelEntityByKey(ctx context.Context, tenantId string, chanKey string) (*entity.TSimChannels, error) { var channel *entity.TSimChannels mod := dao.TSimChannels.Ctx(ctx). Where(dao.TSimChannels.Columns().ChanKey, chanKey). Fields(dao.TSimChannels.Columns().Id, dao.TSimChannels.Columns().ChanKey, dao.TSimChannels.Columns().ChanName, dao.TSimChannels.Columns().ChanAlias, dao.TSimChannels.Columns().TempKey, dao.TSimChannels.Columns().ChanStatus) if tenantId = strings.TrimSpace(tenantId); tenantId != "" { mod = mod.Where(dao.TSimChannels.Columns().TenantId, tenantId) } err := mod.Limit(1).Scan(&channel) if err != nil { return nil, gerror.Wrap(err, "查询通道信息失败") } if channel == nil || channel.Id == 0 { return nil, nil } return channel, nil } func appCardChannelInfoFromEntity(channel *entity.TSimChannels) *appCardChannelInfo { if channel == nil || channel.Id == 0 || strings.TrimSpace(channel.ChanKey) == "" { return nil } return &appCardChannelInfo{ ChanKey: strings.TrimSpace(channel.ChanKey), ChanName: strings.TrimSpace(channel.ChanName), ChanAlias: strings.TrimSpace(channel.ChanAlias), TempKey: strings.TrimSpace(channel.TempKey), ChanStatus: channel.ChanStatus, } }