300 lines
9.0 KiB
Go
300 lines
9.0 KiB
Go
package renew
|
|
|
|
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/model/entity"
|
|
|
|
"github.com/gogf/gf/v2/database/gdb"
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
|
)
|
|
|
|
type Repository struct{}
|
|
|
|
func NewRepository() *Repository {
|
|
return &Repository{}
|
|
}
|
|
|
|
func (r *Repository) GetSourceBatch(ctx context.Context, batchNo string) (*entity.BatchMain, error) {
|
|
batch := &entity.BatchMain{}
|
|
columns := dao.BatchMain.Columns()
|
|
err := dao.BatchMain.Ctx(ctx).
|
|
Fields(
|
|
columns.Id,
|
|
columns.BatchNo,
|
|
columns.BatchType,
|
|
columns.BatchStatus,
|
|
columns.RunResult,
|
|
columns.TenantId,
|
|
columns.DeptId,
|
|
columns.CreatedDept,
|
|
columns.CreatedBy,
|
|
).
|
|
Where(columns.BatchNo, strings.TrimSpace(batchNo)).
|
|
Scan(batch)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if batch.Id == 0 {
|
|
return nil, nil
|
|
}
|
|
return batch, nil
|
|
}
|
|
|
|
func (r *Repository) GetRenewBatchRows(ctx context.Context, batchNo string, batchType int) ([]*Row, error) {
|
|
return r.getRenewBatchRows(ctx, nil, batchNo, batchType)
|
|
}
|
|
|
|
func (r *Repository) GetRenewBatchRowsTx(ctx context.Context, tx gdb.TX, batchNo string, batchType int) ([]*Row, error) {
|
|
return r.getRenewBatchRows(ctx, tx, batchNo, batchType)
|
|
}
|
|
|
|
func (r *Repository) getRenewBatchRows(ctx context.Context, tx gdb.TX, batchNo string, batchType int) ([]*Row, error) {
|
|
var details []*entity.BatchDetail
|
|
columns := dao.BatchDetail.Columns()
|
|
if batchType == 0 {
|
|
batchType = consts.BatchTypeRenew
|
|
}
|
|
model := dao.BatchDetail.Ctx(ctx)
|
|
if tx != nil {
|
|
model = tx.Ctx(ctx).Model(dao.BatchDetail.Table())
|
|
}
|
|
err := model.
|
|
Fields(columns.RowNo, columns.ItemId, columns.Snapshot).
|
|
Where(columns.BatchNo, strings.TrimSpace(batchNo)).
|
|
Where(columns.BatchType, batchType).
|
|
Where(columns.DetailStatus, consts.BatchDetailStatusSuccess).
|
|
OrderAsc(columns.RowNo).
|
|
Scan(&details)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return detailsToRows(details), nil
|
|
}
|
|
|
|
func (r *Repository) GetSourceBatchRows(ctx context.Context, batchNo string) ([]*Row, error) {
|
|
var details []*entity.BatchDetail
|
|
columns := dao.BatchDetail.Columns()
|
|
err := dao.BatchDetail.Ctx(ctx).
|
|
Fields(columns.RowNo, columns.ItemId, columns.Snapshot).
|
|
Where(columns.BatchNo, strings.TrimSpace(batchNo)).
|
|
Where(columns.BatchType, consts.BatchTypeOutbound).
|
|
WhereIn(columns.DetailStatus, []int{consts.BatchDetailStatusSuccess, consts.BatchAsyncStatusSuccess}).
|
|
OrderAsc(columns.RowNo).
|
|
Scan(&details)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return detailsToRows(details), nil
|
|
}
|
|
|
|
func (r *Repository) BatchDetailItemIDs(ctx context.Context, tx gdb.TX, batchNo string, batchType int, statuses []int) ([]string, error) {
|
|
batchNo = strings.TrimSpace(batchNo)
|
|
if batchNo == "" {
|
|
return nil, nil
|
|
}
|
|
var details []*entity.BatchDetail
|
|
model := tx.Ctx(ctx).Model(dao.BatchDetail.Table()).
|
|
Fields(dao.BatchDetail.Columns().ItemId).
|
|
Where(dao.BatchDetail.Columns().BatchNo, batchNo)
|
|
if batchType > 0 {
|
|
model = model.Where(dao.BatchDetail.Columns().BatchType, batchType)
|
|
}
|
|
if len(statuses) > 0 {
|
|
model = model.WhereIn(dao.BatchDetail.Columns().DetailStatus, statuses)
|
|
}
|
|
if err := model.Scan(&details); err != nil {
|
|
return nil, err
|
|
}
|
|
ids := make([]string, 0, len(details))
|
|
for _, detail := range details {
|
|
if detail == nil {
|
|
continue
|
|
}
|
|
if itemID := strings.TrimSpace(detail.ItemId); itemID != "" {
|
|
ids = append(ids, itemID)
|
|
}
|
|
}
|
|
return uniqueStrings(ids), nil
|
|
}
|
|
|
|
func (r *Repository) UnfinishedRenewBatchNosByIccids(ctx context.Context, tx gdb.TX, tenantID string, iccids []string, currentBatchNo string) (map[string]string, error) {
|
|
result := make(map[string]string)
|
|
iccids = uniqueStrings(iccids)
|
|
if len(iccids) == 0 {
|
|
return result, nil
|
|
}
|
|
|
|
currentBatchID, err := r.batchIDByNo(ctx, tx, currentBatchNo)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
type conflictRow struct {
|
|
ItemId string `orm:"item_id"`
|
|
BatchNo string `orm:"batch_no"`
|
|
}
|
|
|
|
bd := "bd"
|
|
bm := "bm"
|
|
detailColumns := dao.BatchDetail.Columns()
|
|
mainColumns := dao.BatchMain.Columns()
|
|
model := tx.Ctx(ctx).Model(dao.BatchDetail.Table()+" "+bd).
|
|
InnerJoin(dao.BatchMain.Table()+" "+bm, bm+"."+mainColumns.BatchNo+" = "+bd+"."+detailColumns.BatchNo).
|
|
Fields(bd+"."+detailColumns.ItemId, bm+"."+mainColumns.BatchNo).
|
|
Where(bd+"."+detailColumns.BatchType, consts.BatchTypeRenew).
|
|
Where(bm+"."+mainColumns.BatchType, consts.BatchTypeRenew).
|
|
Where(bm+"."+mainColumns.BatchStatus, consts.BatchStatusNormal).
|
|
WhereIn(bm+"."+mainColumns.BatchAsyncStatus, []int{
|
|
consts.BatchAsyncStatusCreated,
|
|
consts.BatchAsyncStatusPending,
|
|
consts.BatchAsyncStatusProcessing,
|
|
}).
|
|
WhereIn(bm+"."+mainColumns.RunResult, []int{
|
|
consts.BatchRunResultPending,
|
|
consts.BatchRunResultRunning,
|
|
}).
|
|
WhereIn(bd+"."+detailColumns.DetailStatus, []int{
|
|
consts.BatchDetailStatusPending,
|
|
consts.BatchDetailStatusRunning,
|
|
}).
|
|
WhereIn(bd+"."+detailColumns.ItemId, iccids).
|
|
OrderAsc(bm + "." + mainColumns.Id)
|
|
if strings.TrimSpace(tenantID) != "" {
|
|
model = model.Where(bm+"."+mainColumns.TenantId, strings.TrimSpace(tenantID))
|
|
}
|
|
if currentBatchID > 0 {
|
|
// When duplicate formal renew batches already exist, the earliest batch
|
|
// wins and later batches fail. This prevents two batches from blocking
|
|
// each other forever.
|
|
model = model.Where(bm+"."+mainColumns.Id+" < ?", currentBatchID)
|
|
} else if currentBatchNo = strings.TrimSpace(currentBatchNo); currentBatchNo != "" {
|
|
model = model.Where(bm+"."+mainColumns.BatchNo+" <> ?", currentBatchNo)
|
|
}
|
|
|
|
var rows []conflictRow
|
|
if err := model.Scan(&rows); err != nil {
|
|
return nil, err
|
|
}
|
|
for _, row := range rows {
|
|
itemID := strings.TrimSpace(row.ItemId)
|
|
if itemID == "" {
|
|
continue
|
|
}
|
|
if _, exists := result[itemID]; !exists {
|
|
result[itemID] = strings.TrimSpace(row.BatchNo)
|
|
}
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (r *Repository) batchIDByNo(ctx context.Context, tx gdb.TX, batchNo string) (int64, error) {
|
|
batchNo = strings.TrimSpace(batchNo)
|
|
if batchNo == "" {
|
|
return 0, nil
|
|
}
|
|
batch := &entity.BatchMain{}
|
|
if err := tx.Ctx(ctx).Model(dao.BatchMain.Table()).
|
|
Fields(dao.BatchMain.Columns().Id).
|
|
Where(dao.BatchMain.Columns().BatchNo, batchNo).
|
|
Limit(1).
|
|
Scan(batch); err != nil {
|
|
return 0, err
|
|
}
|
|
return batch.Id, nil
|
|
}
|
|
|
|
func detailsToRows(details []*entity.BatchDetail) []*Row {
|
|
rows := make([]*Row, 0, len(details))
|
|
for _, detail := range details {
|
|
if detail == nil {
|
|
continue
|
|
}
|
|
row := &Row{RowNo: detail.RowNo, Iccid: strings.TrimSpace(detail.ItemId)}
|
|
if detail.Snapshot != nil {
|
|
if row.Iccid == "" {
|
|
row.Iccid = strings.TrimSpace(detail.Snapshot.Get("iccid").String())
|
|
}
|
|
if row.Iccid == "" {
|
|
row.Iccid = strings.TrimSpace(detail.Snapshot.Get("ICCID").String())
|
|
}
|
|
row.Msisdn = strings.TrimSpace(detail.Snapshot.Get("msisdn").String())
|
|
if row.Msisdn == "" {
|
|
row.Msisdn = strings.TrimSpace(detail.Snapshot.Get("MSISDN").String())
|
|
}
|
|
row.Imsi = strings.TrimSpace(detail.Snapshot.Get("imsi").String())
|
|
if row.Imsi == "" {
|
|
row.Imsi = strings.TrimSpace(detail.Snapshot.Get("IMSI").String())
|
|
}
|
|
}
|
|
rows = append(rows, row)
|
|
}
|
|
return rows
|
|
}
|
|
|
|
func (r *Repository) LockCardsByIccids(ctx context.Context, tx gdb.TX, iccids []string) (map[string]*entity.TSimCardInfo, error) {
|
|
result := make(map[string]*entity.TSimCardInfo)
|
|
if len(iccids) == 0 {
|
|
return result, nil
|
|
}
|
|
|
|
var list []*entity.TSimCardInfo
|
|
if err := tx.Ctx(ctx).Model(dao.TSimCardInfo.Table()).
|
|
WhereIn(dao.TSimCardInfo.Columns().Iccid, uniqueStrings(iccids)).
|
|
LockUpdate().
|
|
Scan(&list); err != nil {
|
|
return nil, err
|
|
}
|
|
for _, item := range list {
|
|
if item != nil && strings.TrimSpace(item.Iccid) != "" {
|
|
result[strings.TrimSpace(item.Iccid)] = item
|
|
}
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (r *Repository) LockLatestBindsByIccids(ctx context.Context, tx gdb.TX, iccids []string) (map[string]*entity.TSimCardBindPkg, error) {
|
|
result := make(map[string]*entity.TSimCardBindPkg)
|
|
if len(iccids) == 0 {
|
|
return result, nil
|
|
}
|
|
|
|
var list []*entity.TSimCardBindPkg
|
|
if err := tx.Ctx(ctx).Model(dao.TSimCardBindPkg.Table()).
|
|
WhereIn(dao.TSimCardBindPkg.Columns().Iccid, uniqueStrings(iccids)).
|
|
WhereIn(dao.TSimCardBindPkg.Columns().PackageType, []int{101, 102}).
|
|
WhereIn(dao.TSimCardBindPkg.Columns().EffectiveStatus, []int{
|
|
consts.EffectiveStatusPending,
|
|
consts.EffectiveStatusEffective,
|
|
consts.EffectiveStatusExpired,
|
|
}).
|
|
OrderDesc(dao.TSimCardBindPkg.Columns().ExpectedExpireTime).
|
|
OrderDesc(dao.TSimCardBindPkg.Columns().Id).
|
|
LockUpdate().
|
|
Scan(&list); err != nil {
|
|
return nil, err
|
|
}
|
|
effectiveCount := make(map[string]int)
|
|
for _, item := range list {
|
|
if item == nil || strings.TrimSpace(item.Iccid) == "" {
|
|
continue
|
|
}
|
|
iccid := strings.TrimSpace(item.Iccid)
|
|
if item.EffectiveStatus == consts.EffectiveStatusEffective {
|
|
effectiveCount[iccid]++
|
|
if effectiveCount[iccid] > 1 {
|
|
return nil, gerror.Newf("同一张卡存在多个生效中的套餐订购记录:%s", iccid)
|
|
}
|
|
}
|
|
if _, exists := result[iccid]; exists {
|
|
continue
|
|
}
|
|
result[iccid] = item
|
|
}
|
|
return result, nil
|
|
}
|