chore: 并入 iotlcm-admin-svr 历史到 admin-svr/(原提交 49818c6)

This commit is contained in:
MiFaZhan
2026-11-02 13:27:59 +08:00
1250 changed files with 154111 additions and 0 deletions
@@ -0,0 +1,726 @@
// Package gen
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version
package common
import (
"context"
"fmt"
"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/allocationunits"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/batchmetadata"
"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/library/rabbitmq"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/xgorm"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/xgorm/handler"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/xgorm/hook"
"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/model/entity"
"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/excel"
"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/os/gctx"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv"
)
type sCommonBatchMain struct{}
const restartPhaseWaitingResume = "waiting_resume"
type batchExecuteMessage struct {
BatchNo string `json:"batchNo"`
BatchType int `json:"batchType"`
}
var publishBatchExecuteMessage = rabbitmq.Publish
func NewCommonBatchMain() *sCommonBatchMain {
return &sCommonBatchMain{}
}
func (s *sCommonBatchMain) getRequeueBatch(ctx context.Context, batchNo string) (*entity.BatchMain, error) {
columns := dao.BatchMain.Columns()
batch := &entity.BatchMain{}
err := s.Model(ctx).
Fields(
columns.Id,
columns.BatchNo,
columns.BatchType,
columns.BatchAsyncStatus,
columns.RunResult,
columns.BatchInfo,
columns.TenantId,
columns.DeptId,
columns.CreatedDept,
columns.CreatedBy,
).
Where(columns.BatchNo, batchNo).
Where(columns.BatchType+" <> ?", consts.BatchTypePrepare).
Scan(batch)
if err != nil {
return nil, gerror.Wrap(err, "查询批次信息失败")
}
if batch.Id == 0 {
return nil, gerror.New("批次不存在或无权限")
}
return batch, nil
}
func validateRequeueBatch(batch *entity.BatchMain) error {
if batch == nil {
return gerror.New("批次不存在")
}
switch batch.BatchAsyncStatus {
case consts.BatchAsyncStatusPending:
return nil
case consts.BatchAsyncStatusProcessing:
return validateProcessingRequeueBatch(batch)
case consts.BatchAsyncStatusReview:
return gerror.New("待核查批次不支持安全重投,请先核对上游执行结果")
case consts.BatchAsyncStatusFailed, consts.BatchAsyncStatusSuccess, consts.BatchAsyncStatusPartialSuccess:
return gerror.New("终态批次不支持安全重投")
default:
return gerror.Newf("当前批次状态不支持安全重投,status=%d", batch.BatchAsyncStatus)
}
}
func validateProcessingRequeueBatch(batch *entity.BatchMain) error {
if batch.BatchType != consts.BatchTypeRestart {
return gerror.New("处理中批次不支持安全重投,避免重复调用运营商")
}
if restartPhase(batch) != restartPhaseWaitingResume {
return gerror.New("RST 批次当前不在等待复机阶段,不能安全重投")
}
resumeAt := restartResumeAt(batch)
if resumeAt == nil {
return gerror.New("RST 批次缺少计划复机时间,不能安全重投")
}
if resumeAt.After(gtime.Now()) {
return gerror.Newf("未到计划复机时间,resumeAt=%s", resumeAt.String())
}
return nil
}
func restartPhase(batch *entity.BatchMain) string {
if batch == nil || batch.BatchInfo == nil {
return ""
}
return strings.TrimSpace(batch.BatchInfo.Get("restart.phase").String())
}
func restartResumeAt(batch *entity.BatchMain) *gtime.Time {
if batch == nil || batch.BatchInfo == nil {
return nil
}
value := strings.TrimSpace(batch.BatchInfo.Get("restart.resumeAt").String())
if value == "" {
return nil
}
parsed := gtime.NewFromStr(value)
if parsed == nil || parsed.IsZero() {
return nil
}
return parsed
}
func init() {
service.RegisterCommonBatchMain(NewCommonBatchMain())
}
// Model 批次主表ORM模型
func (s *sCommonBatchMain) Model(ctx context.Context, option ...*handler.Option) *gdb.Model {
if len(option) == 0 {
option = append(option, &handler.Option{
FilterTenant: true,
FilterAuth: true,
})
}
return handler.Model(dao.BatchMain.Ctx(ctx), option...)
}
func (s *sCommonBatchMain) detailModel(ctx context.Context, option ...*handler.Option) *gdb.Model {
if len(option) == 0 {
option = append(option, &handler.Option{
FilterTenant: true,
FilterAuth: true,
})
}
return handler.Model(dao.BatchDetail.Ctx(ctx), option...)
}
// List 获取批次主表列表
func (s *sCommonBatchMain) List(ctx context.Context, in *model.BatchMainListParam) (list []*model.BatchMainListModel, totalCount int, err error) {
mod := s.Model(ctx)
// 字段过滤
mod = mod.Fields(model.BatchMainListModel{})
// 查询主键ID
if in.Id > 0 {
mod = mod.Where(dao.BatchMain.Columns().Id, in.Id)
}
// 查询批次编号
if in.BatchNo != "" {
mod = mod.Where(dao.BatchMain.Columns().BatchNo+" LIKE ?", "%"+in.BatchNo+"%")
}
// 查询订单编号
if in.OrderSn != "" {
mod = mod.Where(dao.BatchMain.Columns().OrderSn+" LIKE ?", "%"+in.OrderSn+"%")
}
// 查询批次类型 枚举
mod = visibleBatchTypeModel(mod, dao.BatchMain.Columns().BatchType, in.BatchType)
// 查询创建时间
if len(in.CreatedAt) == 2 {
in.CreatedAt[1] = in.CreatedAt[1].EndOfDay()
}
if len(in.CreatedAt) == 2 {
mod = mod.WhereBetween(dao.BatchMain.Columns().CreatedAt, in.CreatedAt[0], in.CreatedAt[1])
}
// 分页
mod = mod.Page(in.Page, in.PageSize)
// 排序
mod = mod.OrderDesc(dao.BatchMain.Columns().Id)
// 操作人摘要信息
mod = mod.Hook(hook.MemberSummary)
// 查询数据
if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
err = gerror.Wrap(err, "获取批次主表列表失败,请稍后重试!")
return
}
units := make([]*allocationunits.Fields, 0, len(list))
for _, item := range list {
if item.BatchType == consts.BatchTypeAllocate {
fields := allocationunits.Resolve(item.BatchInfo, item.CreatedDept, item.TargetDeptId)
units = append(units, &fields)
}
}
if err = allocationunits.Fill(ctx, contexts.GetTenantId(ctx), units); err != nil {
return nil, 0, err
}
unitIndex := 0
for _, item := range list {
if item.BatchType == consts.BatchTypeAllocate {
fields := units[unitIndex]
item.SourceDeptId, item.SourceDeptName = fields.SourceDeptId, fields.SourceDeptName
item.TargetDeptId, item.TargetDeptName, item.TargetDeptMode = fields.TargetDeptId, fields.TargetDeptName, fields.TargetDeptMode
unitIndex++
}
}
return
}
func (s *sCommonBatchMain) SuccessList(ctx context.Context, in *model.BatchMainSuccessListParam) (list []*model.BatchMainSuccessListModel, totalCount int, err error) {
if in == nil {
in = &model.BatchMainSuccessListParam{}
}
columns := dao.BatchMain.Columns()
mod := s.Model(ctx).
Fields(
columns.BatchInfo,
columns.BatchNo,
columns.BatchType,
columns.StartTime+" AS batch_time",
columns.TotalCount,
columns.CreatedDept,
columns.TargetDeptId,
).
Where(columns.RunResult, consts.BatchRunResultSuccess).
WhereGT(columns.TotalCount, 0)
var requestedBatchType *int
if in.BatchType != 0 {
requestedBatchType = &in.BatchType
}
mod = successListBatchTypeModel(mod, columns.BatchType, requestedBatchType)
if chanKey := strings.TrimSpace(in.ChanKey); chanKey != "" {
extract := "JSON_UNQUOTE(JSON_EXTRACT(%s, '%s'))"
if strings.EqualFold(dao.BatchMain.DB().GetConfig().Type, "sqlite") {
extract = "JSON_EXTRACT(%s, '%s')"
}
nested := fmt.Sprintf(extract, columns.BatchInfo, "$.inboundOptions.chanKey")
legacy := fmt.Sprintf(extract, columns.BatchInfo, "$.chanKey")
mod = mod.Where(fmt.Sprintf("CASE WHEN JSON_VALID(%s) THEN COALESCE(NULLIF(TRIM(%s), ''), TRIM(%s)) END = ?", columns.BatchInfo, nested, legacy), chanKey)
}
if in.BatchNo != "" {
mod = mod.Where(columns.BatchNo+" LIKE ?", "%"+in.BatchNo+"%")
}
if len(in.Time) == 2 {
in.Time[1] = in.Time[1].EndOfDay()
mod = mod.WhereBetween(columns.StartTime, in.Time[0], in.Time[1])
}
mod = mod.Page(in.Page, in.PageSize).OrderDesc(columns.Id)
if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
return nil, 0, gerror.Wrap(err, "获取成功批次列表失败,请稍后重试")
}
if err = fillInboundBatchStockCounts(ctx, list); err != nil {
return nil, 0, err
}
units := make([]*allocationunits.Fields, 0, len(list))
for _, item := range list {
if item.BatchType == consts.BatchTypeAllocate {
item.Fields = allocationunits.Resolve(item.BatchInfo, item.StoredSourceDeptId, item.StoredTargetDeptId)
units = append(units, &item.Fields)
}
}
if err = allocationunits.Fill(ctx, contexts.GetTenantId(ctx), units); err != nil {
return nil, 0, err
}
return
}
func fillInboundBatchStockCounts(ctx context.Context, list []*model.BatchMainSuccessListModel) error {
if len(list) == 0 {
return nil
}
batchNos := make([]string, 0, len(list))
for _, item := range list {
if item == nil || item.BatchType != consts.BatchTypeInbound || strings.TrimSpace(item.BatchNo) == "" {
continue
}
batchNos = append(batchNos, item.BatchNo)
}
if len(batchNos) == 0 {
return nil
}
type stockCountRow struct {
BatchNo string `orm:"batch_no"`
StockCount int `orm:"stock_count"`
}
var rows []*stockCountRow
stockColumns := dao.TSimCardStock.Columns()
if err := dao.TSimCardStock.Ctx(ctx).
Fields(stockColumns.BatchNo, "COUNT(1) AS stock_count").
Where(stockColumns.TenantId, contexts.GetTenantId(ctx)).
WhereIn(stockColumns.BatchNo, batchNos).
Group(stockColumns.BatchNo).
Scan(&rows); err != nil {
return gerror.Wrap(err, "统计入库批次在库数量失败")
}
stockCountMap := make(map[string]int, len(rows))
for _, row := range rows {
if row != nil {
stockCountMap[row.BatchNo] = row.StockCount
}
}
for _, item := range list {
if item != nil && item.BatchType == consts.BatchTypeInbound {
item.StockCount = stockCountMap[item.BatchNo]
}
}
return nil
}
type batchDetailQuery struct {
BatchNo string
BatchType *int
DetailStatus *int
Iccid string
Msisdn string
CurrentStockOnly bool
Page int
PageSize int
}
func (s *sCommonBatchMain) ListCards(ctx context.Context, in *model.BatchCardListParam) (list []*model.BatchCardListModel, totalCount int, err error) {
if in == nil || in.BatchNo == "" {
return nil, 0, gerror.New("批次号不能为空")
}
batch, err := s.getVisibleBatch(ctx, in.BatchNo, in.BatchType)
if err != nil {
return nil, 0, err
}
details, totalCount, err := s.listBatchDetails(ctx, batch, batchDetailQuery{
DetailStatus: in.DetailStatus,
BatchNo: in.BatchNo,
BatchType: in.BatchType,
Iccid: in.Iccid,
Msisdn: in.Msisdn,
CurrentStockOnly: in.CurrentStockOnly,
Page: in.Page,
PageSize: in.PageSize,
})
if err != nil {
return nil, 0, err
}
list = make([]*model.BatchCardListModel, 0, len(details))
displayRowStart := 0
if in.Page > 0 && in.PageSize > 0 {
displayRowStart = (in.Page - 1) * in.PageSize
}
units := make([]*allocationunits.Fields, 0, len(details))
parentUnits := allocationunits.Resolve(batch.BatchInfo, batch.CreatedDept, batch.TargetDeptId)
for index, detail := range details {
iccid, msisdn, imsi := batchDetailSnapshotCards(detail)
item := &model.BatchCardListModel{
RowNo: displayRowStart + index + 1,
Iccid: iccid,
Msisdn: msisdn,
Imsi: imsi,
DetailStatus: detail.DetailStatus,
ErrorReason: detail.ErrorReason,
}
if batch.BatchType == consts.BatchTypeAllocate {
item.Fields = allocationunits.Resolve(detail.Snapshot, parentUnits.SourceDeptId, parentUnits.TargetDeptId)
if item.SourceDeptName == "" && item.SourceDeptId == parentUnits.SourceDeptId {
item.SourceDeptName = parentUnits.SourceDeptName
}
if item.TargetDeptName == "" && item.TargetDeptId == parentUnits.TargetDeptId {
item.TargetDeptName = parentUnits.TargetDeptName
}
units = append(units, &item.Fields)
}
list = append(list, item)
}
if err = allocationunits.Fill(ctx, contexts.GetTenantId(ctx), units); err != nil {
return nil, 0, err
}
return
}
// listBatchDetails 获取批次卡清单明细。
func (s *sCommonBatchMain) listBatchDetails(ctx context.Context, batch *entity.BatchMain, query batchDetailQuery) (list []*entity.BatchDetail, totalCount int, err error) {
columns := dao.BatchDetail.Columns()
mod := s.detailModel(ctx).
Fields(
columns.Id,
columns.BatchNo,
columns.BatchType,
columns.DetailStatus,
columns.RowNo,
columns.ItemId,
columns.ErrorReason,
columns.Snapshot,
columns.TenantId,
columns.CreatedDept,
columns.CreatedBy,
).
Where(columns.BatchType, batch.BatchType)
if batch.BatchType == consts.BatchTypeAllocate && (batch.SourceBatchNo == "" || batch.SourceBatchNo == batch.BatchNo) {
mainColumns := dao.BatchMain.Columns()
childBatches := s.Model(ctx).Fields(mainColumns.BatchNo).
Where(mainColumns.BatchType, consts.BatchTypeAllocate).
Where(mainColumns.SourceBatchNo, batch.BatchNo).
Where(mainColumns.SourceBatchNo + " <> " + mainColumns.BatchNo)
mod = mod.Where("("+columns.BatchNo+" = ? OR "+columns.BatchNo+" IN (?))", batch.BatchNo, childBatches)
} else {
mod = mod.Where(columns.BatchNo, batch.BatchNo)
}
if query.DetailStatus != nil {
mod = mod.Where(columns.DetailStatus, *query.DetailStatus)
}
if query.Iccid != "" {
like := "%" + query.Iccid + "%"
mod = mod.Where(
"("+columns.ItemId+" LIKE ? OR JSON_UNQUOTE(JSON_EXTRACT("+columns.Snapshot+", '$.ICCID')) LIKE ?)",
like,
like,
)
}
if query.Msisdn != "" {
mod = mod.Where(
"JSON_UNQUOTE(JSON_EXTRACT("+columns.Snapshot+", '$.MSISDN')) LIKE ?",
"%"+query.Msisdn+"%",
)
}
if query.CurrentStockOnly {
mod = onlyCurrentStockDetails(mod)
}
mod = orderBatchCards(mod.Page(query.Page, query.PageSize), batch.BatchType)
if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
return nil, 0, gerror.Wrap(err, "获取批次明细列表失败,请稍后重试")
}
return
}
func orderBatchCards(mod *gdb.Model, batchType int) *gdb.Model {
columns := dao.BatchDetail.Columns()
if batchType == consts.BatchTypeInbound || batchType == consts.BatchTypeOutbound || batchType == consts.BatchTypeAllocate {
order := fmt.Sprintf("CASE WHEN %s = %d AND COALESCE(%s, '') NOT LIKE '本批%%整批未执行%%' AND COALESCE(%s, '') NOT LIKE '同批%%本行未执行%%' AND COALESCE(%s, '') NOT LIKE '同批%%整批未入库%%' THEN 0 ELSE 1 END, %s ASC, %s ASC", columns.DetailStatus, consts.BatchDetailStatusFailed, columns.ErrorReason, columns.ErrorReason, columns.ErrorReason, columns.RowNo, columns.Id)
return mod.Order(gdb.Raw(order))
}
return mod.OrderAsc(columns.RowNo).OrderAsc(columns.Id)
}
func onlyCurrentStockDetails(mod *gdb.Model) *gdb.Model {
detailTable := dao.BatchDetail.Table()
stockTable := dao.TSimCardStock.Table()
return mod.Where(fmt.Sprintf(
"EXISTS (SELECT 1 FROM `%s` stock WHERE stock.`tenant_id` = `%s`.`tenant_id` AND stock.`batch_no` = `%s`.`batch_no` AND stock.`iccid` = COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(`%s`.`snapshot`, '$.ICCID')), ''), `%s`.`item_id`))",
stockTable,
detailTable,
detailTable,
detailTable,
detailTable,
))
}
func (s *sCommonBatchMain) getVisibleBatch(ctx context.Context, batchNo string, batchType *int) (*entity.BatchMain, error) {
if batchNo == "" {
return nil, gerror.New("批次号不能为空")
}
columns := dao.BatchMain.Columns()
batch := &entity.BatchMain{}
mod := s.Model(ctx).
Fields(
columns.Id,
columns.BatchNo,
columns.BatchType,
columns.TenantId,
columns.DeptId,
columns.BatchInfo,
columns.TargetDeptId,
columns.SourceBatchNo,
columns.CreatedDept,
columns.CreatedBy,
).
Where(columns.BatchNo, batchNo)
mod = visibleBatchTypeModel(mod, columns.BatchType, batchType)
if err := mod.Scan(batch); err != nil {
return nil, gerror.Wrap(err, "获取批次信息失败,请稍后重试")
}
if batch.Id == 0 {
return nil, gerror.New("批次不存在")
}
if !visibleBatchTypeMatches(batch.BatchType, batchType) {
return nil, gerror.New("批次类型不匹配")
}
return batch, nil
}
func batchDetailSnapshotCards(detail *entity.BatchDetail) (iccid, msisdn, imsi string) {
if detail == nil {
return
}
if detail.Snapshot != nil {
iccid = strings.TrimSpace(detail.Snapshot.Get("ICCID").String())
msisdn = strings.TrimSpace(detail.Snapshot.Get("MSISDN").String())
imsi = strings.TrimSpace(detail.Snapshot.Get("IMSI").String())
}
if iccid == "" {
iccid = detail.ItemId
}
return
}
// ExportWarehousing 导出入库批次列表(异步:提交任务后到下载中心取文件)。
// 数据来源与入库管理页保持一致:成功批次列表(batch_type=入库)。
func (s *sCommonBatchMain) ExportWarehousing(ctx context.Context, in *model.BatchMainSuccessListParam) (err error) {
if in == nil {
in = &model.BatchMainSuccessListParam{}
}
// 与页面 WarehousingList 一致:固定只导入库批次,不接受调用方传其它类型
in.BatchType = consts.BatchTypeInbound
_, err = exportcenter.Submit(ctx, &exportcenter.Request{
BizKey: "batchMainWarehousing",
BizName: "入库管理",
PermCode: "cpm:iot:tSimCardStock:export",
QueryParam: in,
Tags: func() ([]string, error) {
return convert.GetEntityDescTags(model.BatchMainSuccessListModel{})
},
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.SuccessList(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
}
// Export 导出批次主表
func (s *sCommonBatchMain) Export(ctx context.Context, in *model.BatchMainListParam) (err error) {
list, totalCount, err := s.List(ctx, in)
if err != nil {
return
}
// 字段的排序是依据tags的字段顺序,如果你不想使用默认的排序方式,可以直接定义 tags = []string{"字段名称", "字段名称2", ...}
tags, err := convert.GetEntityDescTags(model.BatchMainExportModel{})
if err != nil {
return
}
var (
fileName = "导出批次主表-" + gctx.CtxId(ctx)
sheetName = fmt.Sprintf("索引条件共%v行,共%v页,当前导出是第%v页,本页共%v行", totalCount, (totalCount+in.PageSize-1)/in.PageSize, in.Page, len(list))
exports []model.BatchMainExportModel
)
if err = gconv.Scan(list, &exports); err != nil {
return
}
err = excel.ExportByStructs(ctx, tags, exports, fileName, sheetName)
return
}
// Edit 修改/新增批次主表
func (s *sCommonBatchMain) Edit(ctx context.Context, in *model.BatchMainEditParam) (err error) {
if in == nil {
return gerror.New("批次参数不能为空")
}
if in.Id <= 0 {
if in.ExecutionMode == nil {
return gerror.New("新建批次必须指定单卡或批量操作规模")
}
if err = batchmetadata.ValidateCreation(batchmetadata.Console, *in.ExecutionMode); err != nil {
return err
}
if *in.ExecutionMode == batchmetadata.Single && (in.TotalCount == nil || *in.TotalCount != 1) {
return gerror.New("单卡批次总数量必须为1")
}
}
data := do.BatchMain{}
if err = gconv.Struct(in, &data); err != nil {
return gerror.Wrap(err, "转换批次参数失败")
}
data.CreatedAt = nil
data.UpdatedAt = nil
// 验证'BatchNo'唯一
if err = xgorm.IsUnique(ctx, &dao.BatchMain, g.Map{dao.BatchMain.Columns().BatchNo: in.BatchNo}, "批次编号已存在", in.Id); err != nil {
return
}
return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
// 修改
if in.Id > 0 {
data.UpdatedBy = contexts.GetUserId(ctx)
data.SourceChannel = nil
data.ExecutionMode = nil
if _, err = s.Model(ctx).TX(tx).
Fields(model.BatchMainUpdateFields{}).
WherePri(in.Id).Data(data).Update(); err != nil {
err = gerror.Wrap(err, "修改批次主表失败,请稍后重试!")
}
return
}
// 新增
data.Id = nil
data.TenantId = contexts.GetTenantId(ctx)
data.CreatedDept = contexts.GetDeptId(ctx)
data.CreatedBy = contexts.GetUserId(ctx)
data.SourceChannel = batchmetadata.Console
data.ExecutionMode = *in.ExecutionMode
if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).TX(tx).
Fields(model.BatchMainInsertFields{}).
Data(data).Insert(); err != nil {
err = gerror.Wrap(err, "新增批次主表失败,请稍后重试!")
}
return
})
}
// Delete 删除批次主表
func (s *sCommonBatchMain) Delete(ctx context.Context, in *model.BatchMainDeleteParam) (err error) {
if _, err = s.Model(ctx).WherePri(in.Id).Unscoped().Delete(); err != nil {
err = gerror.Wrap(err, "删除批次主表失败,请稍后重试!")
return
}
return
}
// View 获取批次主表指定信息
func (s *sCommonBatchMain) Requeue(ctx context.Context, in *model.BatchMainRequeueParam) (res *model.BatchMainRequeueModel, err error) {
if in == nil {
in = &model.BatchMainRequeueParam{}
}
batchNo := strings.TrimSpace(in.BatchNo)
reason := strings.TrimSpace(in.Reason)
if batchNo == "" {
return nil, gerror.New("批次编号不能为空")
}
if reason == "" {
return nil, gerror.New("重投原因不能为空")
}
batch, err := s.getRequeueBatch(ctx, batchNo)
if err != nil {
return nil, err
}
if err = validateRequeueBatch(batch); err != nil {
return nil, err
}
message := batchExecuteMessage{BatchNo: batch.BatchNo, BatchType: batch.BatchType}
if err = publishBatchExecuteMessage(ctx, consts.QueueBatchExecute, message); err != nil {
g.Log().Errorf(ctx, "batch requeue publish failed, batchNo=%s, batchType=%d, tenantId=%s, userId=%d, reason=%s, err=%+v",
batch.BatchNo, batch.BatchType, contexts.GetTenantId(ctx), contexts.GetUserId(ctx), reason, err)
return nil, gerror.Wrap(err, "发布批次重投消息失败")
}
g.Log().Infof(ctx, "batch requeue published, batchNo=%s, batchType=%d, status=%d, runResult=%d, tenantId=%s, userId=%d, reason=%s",
batch.BatchNo, batch.BatchType, batch.BatchAsyncStatus, batch.RunResult, contexts.GetTenantId(ctx), contexts.GetUserId(ctx), reason)
return &model.BatchMainRequeueModel{
BatchNo: batch.BatchNo,
BatchType: batch.BatchType,
BatchAsyncStatus: batch.BatchAsyncStatus,
RunResult: batch.RunResult,
Requeued: true,
}, nil
}
func (s *sCommonBatchMain) View(ctx context.Context, in *model.BatchMainViewParam) (res *model.BatchMainViewModel, err error) {
mod := visibleBatchTypeModel(
s.Model(ctx).WherePri(in.Id),
dao.BatchMain.Columns().BatchType,
nil,
)
if err = mod.Hook(hook.MemberSummary).Scan(&res); err != nil {
err = gerror.Wrap(err, "获取批次主表信息,请稍后重试!")
return
}
if res == nil || res.Id == 0 {
return nil, gerror.New("批次不存在")
}
if res.BatchType == consts.BatchTypeAllocate {
fields := allocationunits.Resolve(res.BatchInfo, res.CreatedDept, res.TargetDeptId)
if err = allocationunits.Fill(ctx, contexts.GetTenantId(ctx), []*allocationunits.Fields{&fields}); err != nil {
return nil, err
}
res.SourceDeptId, res.SourceDeptName = fields.SourceDeptId, fields.SourceDeptName
res.TargetDeptId, res.TargetDeptName, res.TargetDeptMode = fields.TargetDeptId, fields.TargetDeptName, fields.TargetDeptMode
}
return
}