package unsub import ( "context" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/batchmetadata" "strings" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/consts" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/batchimport" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/contexts" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/rabbitmq" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" ) type BatchExecuteMessage struct { BatchNo string `json:"batchNo"` BatchType int `json:"batchType"` } type PendingResult struct { BatchNo string BatchType int BatchAsyncStatus int Total int ValidCount int FailCount int } type Publisher interface { PublishBatch(ctx context.Context, msg BatchExecuteMessage) error } type rabbitPublisher struct{} func (rabbitPublisher) PublishBatch(ctx context.Context, msg BatchExecuteMessage) error { return rabbitmq.Publish(ctx, consts.QueueBatchExecute, msg) } var publisher Publisher = rabbitPublisher{} func SetPublisher(p Publisher) { if p == nil { publisher = rabbitPublisher{} return } publisher = p } func CreatePendingExcel(ctx context.Context, file *ghttp.UploadFile, in *model.TSimCardUnsubExcelSubmitParam) (*PendingResult, error) { if in == nil { in = &model.TSimCardUnsubExcelSubmitParam{} } processor := NewProcessor() req := batchimport.SubmitRequest{ SourceChannel: batchmetadata.Console, ExecutionMode: batchmetadata.Bulk, File: file, BizParams: in, SourceType: consts.BatchSourceTypeFile, Operator: operatorContext(ctx), } result, err := batchimport.CreatePendingUpload(ctx, req, processor, batchimport.PendingOptions{}) if err != nil { return nil, err } return finalizePending(ctx, processor, result), nil } func CreatePendingRange(ctx context.Context, in *model.TSimCardUnsubRangeSubmitParam) (*PendingResult, error) { if in == nil { in = &model.TSimCardUnsubRangeSubmitParam{} } rows, err := BuildRangeRows(ctx, in.StartIccid, in.EndIccid, in.StartMsisdn, in.EndMsisdn, in.StartImsi, in.EndImsi) if err != nil { return nil, err } processor := NewProcessor() req := batchimport.SubmitRequest{ SourceChannel: batchmetadata.Console, ExecutionMode: batchmetadata.Bulk, BizParams: in, SourceType: consts.BatchSourceTypeRange, Operator: operatorContext(ctx), } result, err := batchimport.CreatePendingRows(ctx, req, processor, rows, batchimport.PendingOptions{}) if err != nil { return nil, err } return finalizePending(ctx, processor, result), nil } func CreatePendingInput(ctx context.Context, in *model.TSimCardUnsubInputSubmitParam) (*PendingResult, error) { if in == nil { in = &model.TSimCardUnsubInputSubmitParam{} } rows, err := ParseInputRows(ctx, in.Input) if err != nil { return nil, err } processor := NewProcessor() req := batchimport.SubmitRequest{ SourceChannel: batchmetadata.Console, ExecutionMode: batchmetadata.Bulk, BizParams: in, SourceType: consts.BatchSourceTypeBatchInput, Operator: operatorContext(ctx), } result, err := batchimport.CreatePendingRows(ctx, req, processor, rows, batchimport.PendingOptions{}) if err != nil { return nil, err } return finalizePending(ctx, processor, result), nil } func CreatePendingBatch(ctx context.Context, in *model.TSimCardUnsubBatchSubmitParam) (*PendingResult, error) { if in == nil { in = &model.TSimCardUnsubBatchSubmitParam{} } in.SourceBatchNo = strings.TrimSpace(in.SourceBatchNo) if in.SourceBatchNo == "" { return nil, gerror.New("来源批次号不能为空") } processor := NewProcessor() repo := NewRepository() sourceBatch, err := repo.GetSourceBatch(ctx, in.SourceBatchNo) if err != nil { return nil, gerror.Wrap(err, "查询来源批次失败") } if sourceBatch == nil { return nil, gerror.New("来源批次不存在") } if tenantId := contexts.GetTenantId(ctx); tenantId != "" && sourceBatch.TenantId != tenantId { return nil, gerror.New("来源批次不存在") } if sourceBatch.BatchType != consts.BatchTypeOutbound { return nil, gerror.New("来源批次不是出库批次") } if sourceBatch.RunResult != consts.BatchRunResultSuccess { return nil, gerror.New("来源批次不是成功批次") } rows, err := repo.GetSourceBatchRows(ctx, in.SourceBatchNo) if err != nil { return nil, gerror.Wrap(err, "查询来源批次卡明细失败") } if len(rows) == 0 { return nil, gerror.New("来源批次没有可退订卡") } importRows := make([]batchimport.Row, 0, len(rows)) for _, row := range rows { importRows = append(importRows, row) } req := batchimport.SubmitRequest{ SourceChannel: batchmetadata.Console, ExecutionMode: batchmetadata.Bulk, BizParams: in, SourceType: consts.BatchSourceTypeBatchSelect, SourceBatchNo: in.SourceBatchNo, Operator: operatorContext(ctx), } result, err := batchimport.CreatePendingRows(ctx, req, processor, importRows, batchimport.PendingOptions{}) if err != nil { return nil, err } return finalizePending(ctx, processor, result), nil } func finalizePending(ctx context.Context, p *Processor, result *batchimport.Result) *PendingResult { if result == nil { result = &batchimport.Result{} } if result.BatchType == 0 { result.BatchType = p.Config().BatchType } publishPending(ctx, result.BatchNo, result.BatchType) return pendingResultFromBatch(result, p) } func pendingResultFromBatch(result *batchimport.Result, p *Processor) *PendingResult { if result == nil { return &PendingResult{ BatchType: p.Config().BatchType, BatchAsyncStatus: consts.BatchAsyncStatusPending, } } valid := result.ValidRows if result.TotalRows > 0 && valid == 0 { valid = result.TotalRows - result.ErrorRows if valid < 0 { valid = 0 } } return &PendingResult{ BatchNo: result.BatchNo, BatchType: result.BatchType, BatchAsyncStatus: consts.BatchAsyncStatusPending, Total: result.TotalRows, ValidCount: valid, FailCount: result.ErrorRows, } } func publishPending(ctx context.Context, batchNo string, batchType int) { batchNo = strings.TrimSpace(batchNo) if batchNo == "" { return } if batchType == 0 { batchType = consts.BatchTypeUnsub } msg := BatchExecuteMessage{BatchNo: batchNo, BatchType: batchType} if err := publisher.PublishBatch(ctx, msg); err != nil { g.Log().Errorf(ctx, "unsub batch async publish failed, batchNo=%s, batchType=%d, tenantId=%s, error=%+v", batchNo, batchType, contexts.GetTenantId(ctx), err) } } func operatorContext(ctx context.Context) batchimport.OperatorContext { return batchimport.OperatorContext{ TenantId: contexts.GetTenantId(ctx), DeptId: contexts.GetDeptId(ctx), UserId: contexts.GetUserId(ctx), } }