package iot import ( "context" "strings" "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/library/contexts" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/exportcenter" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/logic/iot/simcardbatch/trafficcutoffconfig" "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" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/utility/convert" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/utility/iot_excelize" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/xuri/excelize/v2" ) type sIotTSimCardTrafficCutoff struct{} func NewIotTSimCardTrafficCutoff() *sIotTSimCardTrafficCutoff { return &sIotTSimCardTrafficCutoff{} } func init() { service.RegisterIotTSimCardTrafficCutoff(NewIotTSimCardTrafficCutoff()) } func (s *sIotTSimCardTrafficCutoff) DownloadExcelTemplate(ctx context.Context) error { f := excelize.NewFile() defer func() { _ = f.Close() }() headers := trafficcutoffconfig.NewProcessor().Config().TemplateHeaders if err := f.SetSheetRow("Sheet1", "A1", &headers); err != nil { return err } if err := iot_excelize.ApplyHeaderColumnsTextStyle(f); err != nil { return err } return iot_excelize.WriteHTTP(ctx, f, "sim_card_traffic_cutoff_config_template") } func (s *sIotTSimCardTrafficCutoff) SubmitExcel(ctx context.Context, in *model.TSimCardTrafficCutoffExcelSubmitParam) (*model.TSimCardTrafficCutoffExcelSubmitRes, error) { if in == nil { in = &model.TSimCardTrafficCutoffExcelSubmitParam{} } file, err := trafficCutoffUploadFile(ctx) if err != nil { return nil, err } result, err := trafficcutoffconfig.CreatePendingExcel(ctx, file, in) if err != nil { return nil, err } return (*model.TSimCardTrafficCutoffExcelSubmitRes)(trafficCutoffSubmitResult(result)), nil } func (s *sIotTSimCardTrafficCutoff) SubmitInput(ctx context.Context, in *model.TSimCardTrafficCutoffInputSubmitParam) (*model.TSimCardTrafficCutoffInputSubmitRes, error) { if in == nil { in = &model.TSimCardTrafficCutoffInputSubmitParam{} } result, err := trafficcutoffconfig.CreatePendingInput(ctx, in) if err != nil { return nil, err } return (*model.TSimCardTrafficCutoffInputSubmitRes)(trafficCutoffSubmitResult(result)), nil } func (s *sIotTSimCardTrafficCutoff) SubmitRange(ctx context.Context, in *model.TSimCardTrafficCutoffRangeSubmitParam) (*model.TSimCardTrafficCutoffRangeSubmitRes, error) { if in == nil { in = &model.TSimCardTrafficCutoffRangeSubmitParam{} } result, err := trafficcutoffconfig.CreatePendingRange(ctx, in) if err != nil { return nil, err } return (*model.TSimCardTrafficCutoffRangeSubmitRes)(trafficCutoffSubmitResult(result)), nil } func (s *sIotTSimCardTrafficCutoff) List(ctx context.Context, in *model.TSimCardTrafficCutoffListParam) (list []*model.TSimCardInfoListModel, total int, err error) { if in == nil { in = &model.TSimCardTrafficCutoffListParam{} } cardParam := in.TSimCardInfoListParam if in.TrafficCutoffStatus == nil { cardParam.TrafficCutoffStatus = []int{1, 2} } else { if *in.TrafficCutoffStatus != 1 && *in.TrafficCutoffStatus != 2 { cardParam.TrafficCutoffStatus = []int{-1} } else { cardParam.TrafficCutoffStatus = []int{*in.TrafficCutoffStatus} } } return service.IotTSimCardInfo().List(ctx, &cardParam) } // Export 导出达量断网(异步:提交任务后到下载中心取文件) func (s *sIotTSimCardTrafficCutoff) Export(ctx context.Context, in *model.TSimCardTrafficCutoffListParam) (err error) { _, err = exportcenter.Submit(ctx, &exportcenter.Request{ BizKey: "tSimCardTrafficCutoff", BizName: "达量断网", PermCode: "cpm:iot:tSimCardTrafficCutoff:export", QueryParam: in, Tags: func() ([]string, error) { return convert.GetEntityDescTags(model.TSimCardInfoListModel{}) }, Fetch: func(ctx context.Context, page, pageSize int) (rows []interface{}, total int, err error) { query := *in query.Page = page query.PageSize = pageSize list, count, err := s.List(ctx, &query) if err != nil { return nil, 0, err } rows = make([]interface{}, 0, len(list)) for _, item := range list { rows = append(rows, item) } return rows, count, nil }, }) return err } func (s *sIotTSimCardTrafficCutoff) Edit(ctx context.Context, in *model.TSimCardTrafficCutoffEditParam) error { if in == nil || in.TrafficCutoffStatus == nil || in.TrafficCutoffThreshold == nil { return gerror.New("达量断网配置参数不能为空") } current, err := loadTrafficCutoffConfig(ctx, in.Id, in.Iccid) if err != nil { return err } crossMonthHold := current.TrafficCutoffCrossMonthHold if in.TrafficCutoffCrossMonthHold != nil { crossMonthHold = *in.TrafficCutoffCrossMonthHold } if *in.TrafficCutoffStatus != 1 && *in.TrafficCutoffStatus != 2 { return gerror.New("达量断网配置状态只能为开启或关闭") } if *in.TrafficCutoffStatus != 1 { crossMonthHold = 0 } if err := trafficcutoffconfig.ValidateConfig(*in.TrafficCutoffStatus, *in.TrafficCutoffThreshold, crossMonthHold); err != nil { return err } data := do.TSimCardTrafficCutoffConfig{ TrafficCutoffStatus: *in.TrafficCutoffStatus, TrafficCutoffThreshold: *in.TrafficCutoffThreshold, TrafficCutoffCrossMonthHold: crossMonthHold, UpdatedBy: contexts.GetUserId(ctx), } if *in.TrafficCutoffStatus != 1 || crossMonthHold == 0 { data.TrafficCutoffTriggeredAt = gdb.Raw("NULL") } _, err = service.IotTSimCardInfo().Model(ctx). Where(dao.TSimCardInfo.Columns().Id, in.Id). Where(dao.TSimCardInfo.Columns().Iccid, in.Iccid). Data(data). Update() return err } func (s *sIotTSimCardTrafficCutoff) Delete(ctx context.Context, in *model.TSimCardTrafficCutoffDeleteParam) error { if in == nil || in.Id <= 0 || strings.TrimSpace(in.Iccid) == "" { return gerror.New("卡片ID和ICCID不能为空") } if err := ensureTrafficCutoffConfigured(ctx, in.Id, in.Iccid); err != nil { return err } _, err := service.IotTSimCardInfo().Model(ctx). Where(dao.TSimCardInfo.Columns().Id, in.Id). Where(dao.TSimCardInfo.Columns().Iccid, in.Iccid). Data(do.TSimCardTrafficCutoffConfig{ TrafficCutoffStatus: 0, TrafficCutoffThreshold: 0, TrafficCutoffCrossMonthHold: 0, TrafficCutoffTriggeredAt: gdb.Raw("NULL"), UpdatedBy: contexts.GetUserId(ctx), }).Update() return err } func ensureTrafficCutoffConfigured(ctx context.Context, id int64, iccid string) error { if id <= 0 || strings.TrimSpace(iccid) == "" { return gerror.New("卡片ID和ICCID不能为空") } var row struct { Id int64 `orm:"id"` TrafficCutoffStatus int `orm:"traffic_cutoff_status"` } columns := dao.TSimCardInfo.Columns() if err := service.IotTSimCardInfo().Model(ctx). Fields(columns.Id, columns.TrafficCutoffStatus). Where(columns.Id, id). Where(columns.Iccid, iccid). Scan(&row); err != nil { return gerror.Wrap(err, "查询达量断网配置失败") } if row.Id == 0 { return gerror.New("卡片不存在、ICCID不匹配或无操作权限") } if row.TrafficCutoffStatus != 1 && row.TrafficCutoffStatus != 2 { return gerror.New("该卡未配置达量断网或配置已变更") } return nil } type trafficCutoffConfigState struct { TrafficCutoffCrossMonthHold int `orm:"traffic_cutoff_cross_month_hold"` } func loadTrafficCutoffConfig(ctx context.Context, id int64, iccid string) (trafficCutoffConfigState, error) { if err := ensureTrafficCutoffConfigured(ctx, id, iccid); err != nil { return trafficCutoffConfigState{}, err } var row trafficCutoffConfigState columns := dao.TSimCardInfo.Columns() if err := service.IotTSimCardInfo().Model(ctx). Fields("traffic_cutoff_cross_month_hold"). Where(columns.Id, id). Where(columns.Iccid, iccid). Scan(&row); err != nil { return trafficCutoffConfigState{}, gerror.Wrap(err, "query traffic cutoff cross-month hold") } return row, nil } func trafficCutoffUploadFile(ctx context.Context) (*ghttp.UploadFile, error) { r := g.RequestFromCtx(ctx) if r == nil { return nil, gerror.New("当前上下文不是HTTP请求") } file := r.GetUploadFile("file") if file == nil { return nil, gerror.New("请选择上传文件") } return file, nil } func trafficCutoffSubmitResult(result *trafficcutoffconfig.PendingResult) *model.TSimCardTrafficCutoffSubmitRes { if result == nil { return &model.TSimCardTrafficCutoffSubmitRes{ BatchType: consts.BatchTypeTrafficCutoffConfig, BatchAsyncStatus: consts.BatchAsyncStatusPending, } } return &model.TSimCardTrafficCutoffSubmitRes{ BatchNo: result.BatchNo, BatchType: result.BatchType, BatchAsyncStatus: result.BatchAsyncStatus, Total: result.Total, ValidCount: result.ValidCount, FailCount: result.FailCount, } }