chore: 初始开源发布
iotlcm-worker-svr:异步执行中枢(RabbitMQ 消费者 + 全量同步编排)。 - Go module:iotlcm-worker-svr → git.5iot.com/iotlcm-public/iotlcm-worker-svr(214 文件) - 凭据与内部标识脱敏:MySQL/Redis 凭据、私网与生产 IP、内网域名、 库名 xiujie_admin → iotlcm、哨兵名占位 - 159 处真实手机号 → 合法 11 位编造号(保留号段与后 4 位,维持互异, 不破坏「校验 MSISDN 格式」等测试断言) - 移除内部资产:CI 触发器、Jenkins 触发测试文档、预演门禁与镜像 digest 记录 - Dockerfile 改用公共基础镜像(golang:1.25-alpine → alpine:3.23), 移除写死的 git 凭据 - README 重写(架构/全量同步模型/配置/已知失败),补 Apache-2.0 LICENSE,LF 行尾 + .gitattributes 已知:3 个测试包在源仓同一提交上同样失败(client/upstream、 service/allocate、service/inbound),属既有缺陷,本仓未引入亦未修复。
This commit is contained in:
@@ -0,0 +1,529 @@
|
||||
package renewchange
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
|
||||
"git.5iot.com/iotlcm-public/iotlcm-worker-svr/internal/consts"
|
||||
)
|
||||
|
||||
// Repository 提供对续费/变更相关表的 typed 访问。
|
||||
// 表名/列名都是常量(见 tables.go),与 Admin 同步链路保持一致。
|
||||
type Repository struct{}
|
||||
|
||||
func New() *Repository {
|
||||
return &Repository{}
|
||||
}
|
||||
|
||||
const simCardRenewChangeFields = "id,iccid,msisdn,imsi,dept_id,current_package_code,package_status,outbound_batch_no,flow_pkg_begin_at,flow_pkg_end_at,tenant_id,created_dept,updated_by,updated_at"
|
||||
|
||||
func (r *Repository) database() gdb.DB {
|
||||
return db()
|
||||
}
|
||||
|
||||
// DB 返回底层 gdb.DB,供 service 层发起事务。
|
||||
func (r *Repository) DB() gdb.DB {
|
||||
return r.database()
|
||||
}
|
||||
|
||||
// LoadBatchMain 按 batchNo+batchType 加载。
|
||||
func (r *Repository) LoadBatchMain(ctx context.Context, batchNo string, batchType int) (*BatchMainRow, error) {
|
||||
if batchNo == "" {
|
||||
return nil, gerror.New("batch number is empty")
|
||||
}
|
||||
m := r.database().Model(TableBatchMain).Safe().Ctx(ctx).
|
||||
Where("batch_no", batchNo).
|
||||
Where("batch_type", batchType)
|
||||
var out BatchMainRow
|
||||
if err := m.Scan(&out); err != nil {
|
||||
return nil, gerror.Wrap(err, "query batch main failed")
|
||||
}
|
||||
if out.Id == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
// LoadBatchDetails 加载指定批次下指定状态集合的明细。
|
||||
func (r *Repository) LoadBatchDetails(ctx context.Context, batchNo string, batchType int, statuses []int) ([]*BatchDetailRow, error) {
|
||||
if batchNo == "" {
|
||||
return nil, nil
|
||||
}
|
||||
m := r.database().Model(TableBatchDetail).Safe().Ctx(ctx).
|
||||
Where("batch_no", batchNo).
|
||||
Where("batch_type", batchType).
|
||||
OrderAsc("row_no")
|
||||
if len(statuses) > 0 {
|
||||
m = m.WhereIn("detail_status", statuses)
|
||||
}
|
||||
var out []*BatchDetailRow
|
||||
if err := m.Scan(&out); err != nil {
|
||||
return nil, gerror.Wrap(err, "query batch details failed")
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (r *Repository) LoadCardsByIdentityValues(ctx context.Context, tenantID string, values []string) ([]*SimCardInfo, error) {
|
||||
uniq := uniqueStrings(values)
|
||||
if len(uniq) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
tenantID = strings.TrimSpace(tenantID)
|
||||
byID := map[int64]*SimCardInfo{}
|
||||
for _, column := range []string{"iccid", "msisdn", "imsi"} {
|
||||
var rows []*SimCardInfo
|
||||
query := r.database().Model(TableSimCardInfo).Safe().Ctx(ctx).
|
||||
Fields(simCardRenewChangeFields).
|
||||
WhereIn(column, uniq)
|
||||
if tenantID != "" {
|
||||
query = query.Where("tenant_id", tenantID)
|
||||
}
|
||||
if err := query.Scan(&rows); err != nil {
|
||||
return nil, gerror.Wrap(err, "query sim cards by identity failed")
|
||||
}
|
||||
for _, row := range rows {
|
||||
if row != nil && row.Id > 0 {
|
||||
byID[row.Id] = row
|
||||
}
|
||||
}
|
||||
}
|
||||
out := make([]*SimCardInfo, 0, len(byID))
|
||||
for _, row := range byID {
|
||||
out = append(out, row)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// UpdateBatchMainStatus 在事务内更新主表。
|
||||
func (r *Repository) UpdateBatchMainStatus(ctx context.Context, tx gdb.TX, batchNo string, batchType int, data *BatchMainRow) error {
|
||||
updateData := map[string]any{
|
||||
"batch_type": data.BatchType,
|
||||
"batch_async_status": data.BatchAsyncStatus,
|
||||
"run_result": data.RunResult,
|
||||
"total_count": data.TotalCount,
|
||||
"valid_count": data.ValidCount,
|
||||
"success_count": data.SuccessCount,
|
||||
"fail_count": data.FailCount,
|
||||
"fail_reason": data.FailReason,
|
||||
"batch_info": data.BatchInfo,
|
||||
"end_time": data.EndTime,
|
||||
"updated_by": data.UpdatedBy,
|
||||
"updated_at": gtime.Now(),
|
||||
"order_sn": data.OrderSn,
|
||||
"target_dept_id": data.TargetDeptId,
|
||||
}
|
||||
if data.StartTime != nil && !data.StartTime.IsZero() {
|
||||
updateData["start_time"] = data.StartTime
|
||||
}
|
||||
_, err := tx.Ctx(ctx).Model(TableBatchMain).
|
||||
Where("batch_no", batchNo).
|
||||
Where("batch_type", batchType).
|
||||
Data(updateData).
|
||||
Update()
|
||||
return gerror.Wrap(err, "update batch main failed")
|
||||
}
|
||||
|
||||
// ConvertBatchDetails 将指定状态的明细转换为目标类型与状态。
|
||||
func (r *Repository) ConvertBatchDetails(ctx context.Context, tx gdb.TX, batchNo string, fromTypes []int, toType, toStatus int, data map[string]any) (int64, error) {
|
||||
if data == nil {
|
||||
data = map[string]any{}
|
||||
}
|
||||
data["batch_type"] = toType
|
||||
data["detail_status"] = toStatus
|
||||
data["updated_at"] = gtime.Now()
|
||||
result, err := tx.Ctx(ctx).Model(TableBatchDetail).
|
||||
Where("batch_no", batchNo).
|
||||
WhereIn("batch_type", fromTypes).
|
||||
Data(data).
|
||||
Update()
|
||||
if err != nil {
|
||||
return 0, gerror.Wrap(err, "convert batch details failed")
|
||||
}
|
||||
affected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return affected, nil
|
||||
}
|
||||
|
||||
// UpdateBatchDetailSnapshot 覆盖指定明细的 snapshot 与状态。
|
||||
func (r *Repository) UpdateBatchDetailSnapshot(ctx context.Context, tx gdb.TX, batchNo string, batchType, rowNo int, status int, snapshot *gjson.Json, reason string, userID int64) error {
|
||||
data := map[string]any{
|
||||
"detail_status": status,
|
||||
"snapshot": snapshot,
|
||||
"updated_at": gtime.Now(),
|
||||
"updated_by": userID,
|
||||
}
|
||||
if reason != "" {
|
||||
data["error_reason"] = reason
|
||||
}
|
||||
_, err := tx.Ctx(ctx).Model(TableBatchDetail).
|
||||
Where("batch_no", batchNo).
|
||||
Where("batch_type", batchType).
|
||||
Where("row_no", rowNo).
|
||||
Data(data).
|
||||
Update()
|
||||
return gerror.Wrap(err, "update batch detail snapshot failed")
|
||||
}
|
||||
|
||||
// UpsertBatchDetail 按 (batch_no, batch_type, row_no) 写入明细(覆盖式)。
|
||||
func (r *Repository) UpsertBatchDetail(ctx context.Context, tx gdb.TX, detail *BatchDetailRow) error {
|
||||
_, err := tx.Ctx(ctx).Model(TableBatchDetail).
|
||||
Where("batch_no", detail.BatchNo).
|
||||
Where("batch_type", detail.BatchType).
|
||||
Where("row_no", detail.RowNo).
|
||||
Data(map[string]any{
|
||||
"detail_status": detail.DetailStatus,
|
||||
"blank_out_status": detail.BlankOutStatus,
|
||||
"item_id": detail.ItemId,
|
||||
"error_code": detail.ErrorCode,
|
||||
"error_reason": detail.ErrorReason,
|
||||
"snapshot": detail.Snapshot,
|
||||
"updated_at": gtime.Now(),
|
||||
"updated_by": detail.UpdatedBy,
|
||||
}).
|
||||
Update()
|
||||
if err != nil {
|
||||
return gerror.Wrap(err, "update batch detail failed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadCardsByIccids 加载正式卡。
|
||||
func (r *Repository) LoadCardsByIccids(ctx context.Context, iccids []string) (map[string]*SimCardInfo, error) {
|
||||
out := make(map[string]*SimCardInfo, len(iccids))
|
||||
uniq := uniqueStrings(iccids)
|
||||
if len(uniq) == 0 {
|
||||
return out, nil
|
||||
}
|
||||
var rows []*SimCardInfo
|
||||
if err := r.database().Model(TableSimCardInfo).Safe().Ctx(ctx).
|
||||
Fields(simCardRenewChangeFields).
|
||||
WhereIn("iccid", uniq).
|
||||
Scan(&rows); err != nil {
|
||||
return nil, gerror.Wrap(err, "query sim cards failed")
|
||||
}
|
||||
for _, row := range rows {
|
||||
if row == nil {
|
||||
continue
|
||||
}
|
||||
row.Iccid = strings.TrimSpace(row.Iccid)
|
||||
if row.Iccid == "" {
|
||||
continue
|
||||
}
|
||||
out[row.Iccid] = row
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// LockCardsByIccids 在事务内按 ICCID 锁行加载正式卡。
|
||||
func (r *Repository) LockCardsByIccids(ctx context.Context, tx gdb.TX, iccids []string) (map[string]*SimCardInfo, error) {
|
||||
out := make(map[string]*SimCardInfo, len(iccids))
|
||||
uniq := uniqueStrings(iccids)
|
||||
if len(uniq) == 0 {
|
||||
return out, nil
|
||||
}
|
||||
var rows []*SimCardInfo
|
||||
if err := tx.Ctx(ctx).Model(TableSimCardInfo).
|
||||
Fields(simCardRenewChangeFields).
|
||||
WhereIn("iccid", uniq).
|
||||
LockUpdate().
|
||||
Scan(&rows); err != nil {
|
||||
return nil, gerror.Wrap(err, "lock sim cards failed")
|
||||
}
|
||||
for _, row := range rows {
|
||||
if row == nil {
|
||||
continue
|
||||
}
|
||||
row.Iccid = strings.TrimSpace(row.Iccid)
|
||||
if row.Iccid == "" {
|
||||
continue
|
||||
}
|
||||
out[row.Iccid] = row
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// LoadActiveBindRowsByIccids loads every pending/effective formal package
|
||||
// subscription for prepare validation. Add-on package rows (103/104) are
|
||||
// intentionally excluded from current-subscription selection.
|
||||
func (r *Repository) LoadActiveBindRowsByIccids(ctx context.Context, iccids []string) ([]*SimCardBindPkg, error) {
|
||||
uniq := uniqueStrings(iccids)
|
||||
if len(uniq) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var rows []*SimCardBindPkg
|
||||
if err := r.database().Ctx(ctx).Model(TableSimCardBindPkg).
|
||||
WhereIn("iccid", uniq).
|
||||
WhereIn("package_type", consts.FormalPackageTypes()).
|
||||
WhereIn("effective_status", []int{consts.EffectiveStatusPending, consts.EffectiveStatusEffective}).
|
||||
OrderDesc("effective_status").
|
||||
OrderAsc("effective_time").
|
||||
OrderAsc("id").
|
||||
Scan(&rows); err != nil {
|
||||
return nil, gerror.Wrap(err, "load active binds failed")
|
||||
}
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
// LoadRenewBindRowsByIccids includes expired formal-package history so renewal
|
||||
// can restart after a card has naturally expired. Add-on package rows (103/104)
|
||||
// never participate in renewal selection.
|
||||
func (r *Repository) LoadRenewBindRowsByIccids(ctx context.Context, iccids []string) ([]*SimCardBindPkg, error) {
|
||||
uniq := uniqueStrings(iccids)
|
||||
if len(uniq) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var rows []*SimCardBindPkg
|
||||
if err := r.database().Ctx(ctx).Model(TableSimCardBindPkg).
|
||||
WhereIn("iccid", uniq).
|
||||
WhereIn("package_type", consts.FormalPackageTypes()).
|
||||
WhereIn("effective_status", []int{
|
||||
consts.EffectiveStatusPending,
|
||||
consts.EffectiveStatusEffective,
|
||||
consts.EffectiveStatusExpired,
|
||||
}).
|
||||
OrderDesc("effective_status").
|
||||
OrderAsc("effective_time").
|
||||
OrderAsc("id").
|
||||
Scan(&rows); err != nil {
|
||||
return nil, gerror.Wrap(err, "load renew binds failed")
|
||||
}
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
// LockActiveBindRowsByIccids is the transactional counterpart used by change
|
||||
// execution before any business write. It locks formal package rows only.
|
||||
func (r *Repository) LockActiveBindRowsByIccids(ctx context.Context, tx gdb.TX, iccids []string) ([]*SimCardBindPkg, error) {
|
||||
uniq := uniqueStrings(iccids)
|
||||
if len(uniq) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var rows []*SimCardBindPkg
|
||||
if err := tx.Ctx(ctx).Model(TableSimCardBindPkg).
|
||||
WhereIn("iccid", uniq).
|
||||
WhereIn("package_type", consts.FormalPackageTypes()).
|
||||
WhereIn("effective_status", []int{consts.EffectiveStatusPending, consts.EffectiveStatusEffective}).
|
||||
OrderDesc("effective_status").
|
||||
OrderAsc("effective_time").
|
||||
OrderAsc("id").
|
||||
LockUpdate().
|
||||
Scan(&rows); err != nil {
|
||||
return nil, gerror.Wrap(err, "lock active binds failed")
|
||||
}
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
// LockRenewBindRowsByIccids includes expired formal-package history for renewal
|
||||
// execution. Change execution keeps using LockActiveBindRowsByIccids.
|
||||
func (r *Repository) LockRenewBindRowsByIccids(ctx context.Context, tx gdb.TX, iccids []string) ([]*SimCardBindPkg, error) {
|
||||
uniq := uniqueStrings(iccids)
|
||||
if len(uniq) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var rows []*SimCardBindPkg
|
||||
if err := tx.Ctx(ctx).Model(TableSimCardBindPkg).
|
||||
WhereIn("iccid", uniq).
|
||||
WhereIn("package_type", consts.FormalPackageTypes()).
|
||||
WhereIn("effective_status", []int{
|
||||
consts.EffectiveStatusPending,
|
||||
consts.EffectiveStatusEffective,
|
||||
consts.EffectiveStatusExpired,
|
||||
}).
|
||||
OrderDesc("effective_status").
|
||||
OrderAsc("effective_time").
|
||||
OrderAsc("id").
|
||||
LockUpdate().
|
||||
Scan(&rows); err != nil {
|
||||
return nil, gerror.Wrap(err, "lock renew binds failed")
|
||||
}
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
// LockPendingBindsByIccids 锁行加载 pending 状态的未来订购。
|
||||
func (r *Repository) LockPendingBindsByIccids(ctx context.Context, tx gdb.TX, iccids []string) ([]*SimCardBindPkg, error) {
|
||||
uniq := uniqueStrings(iccids)
|
||||
if len(uniq) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var rows []*SimCardBindPkg
|
||||
if err := tx.Ctx(ctx).Model(TableSimCardBindPkg).
|
||||
WhereIn("iccid", uniq).
|
||||
WhereIn("package_type", consts.FormalPackageTypes()).
|
||||
Where("effective_status", consts.EffectiveStatusPending).
|
||||
OrderAsc("effective_time").
|
||||
OrderAsc("id").
|
||||
LockUpdate().
|
||||
Scan(&rows); err != nil {
|
||||
return nil, gerror.Wrap(err, "lock pending binds failed")
|
||||
}
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
// DeletePendingBindsBySubscriptionNos 删除(作废)一批订阅号。
|
||||
func (r *Repository) DeletePendingBindsBySubscriptionNos(ctx context.Context, tx gdb.TX, subscriptionNos []string) (int64, error) {
|
||||
uniq := uniqueStrings(subscriptionNos)
|
||||
if len(uniq) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
result, err := tx.Ctx(ctx).Model(TableSimCardBindPkg).
|
||||
WhereIn("subscription_no", uniq).
|
||||
Delete()
|
||||
if err != nil {
|
||||
return 0, gerror.Wrap(err, "delete pending binds failed")
|
||||
}
|
||||
affected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return affected, nil
|
||||
}
|
||||
|
||||
// LoadPackageByCode 按 packageCode 读取套餐。
|
||||
func (r *Repository) LoadPackageByCode(ctx context.Context, tenantID, packageCode string) (*FlowPackageInfo, error) {
|
||||
if packageCode == "" {
|
||||
return nil, errPkgNotFound
|
||||
}
|
||||
var row FlowPackageInfo
|
||||
err := r.database().Model(TableSimFlowPackageInfo).Safe().Ctx(ctx).
|
||||
Where("tenant_id", tenantID).
|
||||
Where("package_code", strings.TrimSpace(packageCode)).
|
||||
Scan(&row)
|
||||
if err != nil {
|
||||
return nil, gerror.Wrap(err, "query package failed")
|
||||
}
|
||||
if row.Id == 0 {
|
||||
return nil, errPkgNotFound
|
||||
}
|
||||
return &row, nil
|
||||
}
|
||||
|
||||
// LoadDeptName 按 deptId 取客户名。
|
||||
func (r *Repository) LoadDeptName(ctx context.Context, tenantID string, deptID int64) (string, error) {
|
||||
row, err := r.LoadDept(ctx, tenantID, deptID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.TrimSpace(row.DeptName), nil
|
||||
}
|
||||
|
||||
// LoadDept returns the current department and its parent. Renewals use the
|
||||
// parent department as the price owner for the current card owner.
|
||||
func (r *Repository) LoadDept(ctx context.Context, tenantID string, deptID int64) (*SysDeptRow, error) {
|
||||
if deptID <= 0 {
|
||||
return nil, errDeptNotFound
|
||||
}
|
||||
var row SysDeptRow
|
||||
err := r.database().Model(TableSysDept).Safe().Ctx(ctx).
|
||||
Where("tenant_id", tenantID).
|
||||
Where("dept_id", deptID).
|
||||
Scan(&row)
|
||||
if err != nil {
|
||||
return nil, gerror.Wrap(err, "query dept failed")
|
||||
}
|
||||
if row.DeptId == 0 {
|
||||
return nil, errDeptNotFound
|
||||
}
|
||||
return &row, nil
|
||||
}
|
||||
|
||||
// LoadPriceOverride 读取代理续费/变更价格覆盖。
|
||||
func (r *Repository) LoadPriceOverride(ctx context.Context, tenantID string, deptID, targetAgentID int64, scopeType int, packageCode string) (*FlowPackagePrice, error) {
|
||||
var row FlowPackagePrice
|
||||
err := r.database().Model(TableSimFlowPackagePrice).Safe().Ctx(ctx).
|
||||
Where("tenant_id", tenantID).
|
||||
Where("dept_id", deptID).
|
||||
Where("agent_scope_type", scopeType).
|
||||
Where("target_agent_id", targetAgentID).
|
||||
Where("package_code", strings.TrimSpace(packageCode)).
|
||||
Where("enabled", 1).
|
||||
Scan(&row)
|
||||
return normalizePriceOverrideResult(&row, err)
|
||||
}
|
||||
|
||||
func normalizePriceOverrideResult(row *FlowPackagePrice, err error) (*FlowPackagePrice, error) {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, gerror.Wrap(err, "query price override failed")
|
||||
}
|
||||
if row == nil || row.Id == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return row, nil
|
||||
}
|
||||
|
||||
// UpdateCardPackageFields 续费/变更后更新卡的当前套餐与流量状态。
|
||||
func (r *Repository) UpdateCardPackageFields(ctx context.Context, tx gdb.TX, iccid string, fields map[string]any, userID int64) error {
|
||||
if iccid == "" {
|
||||
return gerror.New("iccid is empty")
|
||||
}
|
||||
fields["updated_by"] = userID
|
||||
fields["updated_at"] = gtime.Now()
|
||||
_, err := tx.Ctx(ctx).Model(TableSimCardInfo).
|
||||
Where("iccid", iccid).
|
||||
Data(fields).
|
||||
Update()
|
||||
return gerror.Wrap(err, "update sim card failed")
|
||||
}
|
||||
|
||||
// InsertOrder 插入订单(返回 orderSn)。
|
||||
// InsertOrderItem 插入订单项。
|
||||
// UpdateOrderReturnStatus 更新订单退订状态。
|
||||
// UpdateOrderItemExtra 合并并写入订单项 extraSkuData(JSON 字符串)。
|
||||
// ActiveBindCountByOrderCodes 统计订单当前未作废的订购数。
|
||||
func (r *Repository) ActiveBindCountByOrderCodes(ctx context.Context, tx gdb.TX, orderSNs []string) (map[string]int, error) {
|
||||
out := make(map[string]int, len(orderSNs))
|
||||
uniq := uniqueStrings(orderSNs)
|
||||
if len(uniq) == 0 {
|
||||
return out, nil
|
||||
}
|
||||
type row struct {
|
||||
OrderCode string `orm:"order_code"`
|
||||
Count int `orm:"count"`
|
||||
}
|
||||
var rows []row
|
||||
if err := tx.Ctx(ctx).Model(TableSimCardBindPkg).
|
||||
Fields("order_code", "COUNT(1) AS count").
|
||||
WhereIn("order_code", uniq).
|
||||
Group("order_code").
|
||||
Scan(&rows); err != nil {
|
||||
return nil, gerror.Wrap(err, "count active binds failed")
|
||||
}
|
||||
for _, r := range rows {
|
||||
out[strings.TrimSpace(r.OrderCode)] = r.Count
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// InsertBind 插入新的订购记录。
|
||||
func (r *Repository) InsertBind(ctx context.Context, tx gdb.TX, bind *SimCardBindPkg) error {
|
||||
_, err := tx.Ctx(ctx).Model(TableSimCardBindPkg).Data(bind).Insert()
|
||||
return gerror.Wrap(err, "insert bind failed")
|
||||
}
|
||||
|
||||
// InsertSysOss 插入 OSS 记录,返回 ID。
|
||||
func (r *Repository) InsertSysOss(ctx context.Context, tx gdb.TX, row *SysOssRow) (int64, error) {
|
||||
id, err := tx.Ctx(ctx).Model(TableSysOss).Data(row).InsertAndGetId()
|
||||
if err != nil {
|
||||
return 0, gerror.Wrap(err, "insert sys oss failed")
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// InsertBatchDownload 插入 t_resource_batch_download 记录,返回 ID。
|
||||
func (r *Repository) InsertBatchDownload(ctx context.Context, tx gdb.TX, row *ResourceBatchDownloadRow) (int64, error) {
|
||||
id, err := tx.Ctx(ctx).Model(TableTResourceBatchDl).Data(row).InsertAndGetId()
|
||||
if err != nil {
|
||||
return 0, gerror.Wrap(err, "insert batch download failed")
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
Reference in New Issue
Block a user