package iot_card import ( "context" "github.com/break/junhong_cmp_fiber/internal/model" "github.com/break/junhong_cmp_fiber/internal/model/dto" "github.com/break/junhong_cmp_fiber/internal/store" "github.com/break/junhong_cmp_fiber/internal/store/postgres" "github.com/break/junhong_cmp_fiber/pkg/constants" "gorm.io/gorm" ) type Service struct { db *gorm.DB iotCardStore *postgres.IotCardStore } func New(db *gorm.DB, iotCardStore *postgres.IotCardStore) *Service { return &Service{ db: db, iotCardStore: iotCardStore, } } func (s *Service) ListStandalone(ctx context.Context, req *dto.ListStandaloneIotCardRequest) (*dto.ListStandaloneIotCardResponse, error) { page := req.Page pageSize := req.PageSize if page == 0 { page = 1 } if pageSize == 0 { pageSize = constants.DefaultPageSize } opts := &store.QueryOptions{ Page: page, PageSize: pageSize, } filters := make(map[string]interface{}) if req.Status != nil { filters["status"] = *req.Status } if req.CarrierID != nil { filters["carrier_id"] = *req.CarrierID } if req.ShopID != nil { filters["shop_id"] = *req.ShopID } if req.ICCID != "" { filters["iccid"] = req.ICCID } if req.MSISDN != "" { filters["msisdn"] = req.MSISDN } if req.BatchNo != "" { filters["batch_no"] = req.BatchNo } if req.PackageID != nil { filters["package_id"] = *req.PackageID } if req.IsDistributed != nil { filters["is_distributed"] = *req.IsDistributed } if req.ICCIDStart != "" { filters["iccid_start"] = req.ICCIDStart } if req.ICCIDEnd != "" { filters["iccid_end"] = req.ICCIDEnd } if req.IsReplaced != nil { filters["is_replaced"] = *req.IsReplaced } cards, total, err := s.iotCardStore.ListStandalone(ctx, opts, filters) if err != nil { return nil, err } carrierMap, shopMap := s.loadRelatedData(ctx, cards) list := make([]*dto.StandaloneIotCardResponse, 0, len(cards)) for _, card := range cards { item := s.toStandaloneResponse(card, carrierMap, shopMap) list = append(list, item) } totalPages := int(total) / pageSize if int(total)%pageSize > 0 { totalPages++ } return &dto.ListStandaloneIotCardResponse{ List: list, Total: total, Page: page, PageSize: pageSize, TotalPages: totalPages, }, nil } func (s *Service) loadRelatedData(ctx context.Context, cards []*model.IotCard) (map[uint]string, map[uint]string) { carrierIDs := make([]uint, 0) shopIDs := make([]uint, 0) carrierIDSet := make(map[uint]bool) shopIDSet := make(map[uint]bool) for _, card := range cards { if card.CarrierID > 0 && !carrierIDSet[card.CarrierID] { carrierIDs = append(carrierIDs, card.CarrierID) carrierIDSet[card.CarrierID] = true } if card.ShopID != nil && *card.ShopID > 0 && !shopIDSet[*card.ShopID] { shopIDs = append(shopIDs, *card.ShopID) shopIDSet[*card.ShopID] = true } } carrierMap := make(map[uint]string) if len(carrierIDs) > 0 { var carriers []model.Carrier s.db.WithContext(ctx).Where("id IN ?", carrierIDs).Find(&carriers) for _, c := range carriers { carrierMap[c.ID] = c.CarrierName } } shopMap := make(map[uint]string) if len(shopIDs) > 0 { var shops []model.Shop s.db.WithContext(ctx).Where("id IN ?", shopIDs).Find(&shops) for _, shop := range shops { shopMap[shop.ID] = shop.ShopName } } return carrierMap, shopMap } func (s *Service) toStandaloneResponse(card *model.IotCard, carrierMap map[uint]string, shopMap map[uint]string) *dto.StandaloneIotCardResponse { resp := &dto.StandaloneIotCardResponse{ ID: card.ID, ICCID: card.ICCID, CardType: card.CardType, CardCategory: card.CardCategory, CarrierID: card.CarrierID, CarrierName: carrierMap[card.CarrierID], IMSI: card.IMSI, MSISDN: card.MSISDN, BatchNo: card.BatchNo, Supplier: card.Supplier, CostPrice: card.CostPrice, DistributePrice: card.DistributePrice, Status: card.Status, ShopID: card.ShopID, ActivatedAt: card.ActivatedAt, ActivationStatus: card.ActivationStatus, RealNameStatus: card.RealNameStatus, NetworkStatus: card.NetworkStatus, DataUsageMB: card.DataUsageMB, CreatedAt: card.CreatedAt, UpdatedAt: card.UpdatedAt, } if card.ShopID != nil && *card.ShopID > 0 { resp.ShopName = shopMap[*card.ShopID] } return resp }