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:
MiFaZhan
2026-10-22 16:37:56 +08:00
commit 2bec257289
361 changed files with 71524 additions and 0 deletions
+392
View File
@@ -0,0 +1,392 @@
package renewchange
import (
"encoding/json"
"sort"
"strings"
"time"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
)
const (
TableSimCardInfo = "t_sim_card_info"
TableSimCardBindPkg = "t_sim_card_bind_pkg"
TableSimPoolBindPackage = "t_sim_pool_bind_package"
TableSimBindPackageLogs = "t_sim_bind_package_logs"
TableOrder = "t_order"
TableOrderItem = "t_order_item"
TableSimFlowPackageInfo = "t_sim_flow_package_info"
TableSimFlowPackagePrice = "t_sim_flow_package_price"
TableSysDept = "sys_dept"
TableBatchMain = "batch_main"
TableBatchDetail = "batch_detail"
TableAgentBalance = "t_agent_balance"
TableBalanceDetail = "t_balance_detail"
TableSysOss = "sys_oss"
TableTResourceBatchDl = "t_resource_batch_download"
)
// typed row structs(worker 端未生成 DAO/DO/entity,故使用本地 typed struct)。
type SimCardInfo struct {
Id int64 `orm:"id"`
Iccid string `orm:"iccid"`
Msisdn string `orm:"msisdn"`
Imsi string `orm:"imsi"`
RegionCode string `orm:"region_code"`
DeptId int64 `orm:"dept_id"`
AllocationBatchNo string `orm:"allocation_batch_no"`
CurrentPackageCode string `orm:"current_package_code"`
PackageStatus int `orm:"package_status"`
ChanKey string `orm:"chan_key"`
OutboundBatchNo string `orm:"outbound_batch_no"`
InboundBatchNo string `orm:"inbound_batch_no"`
FlowPkgBeginAt *gtime.Time `orm:"flow_pkg_begin_at"`
FlowPkgPresentAt *gtime.Time `orm:"flow_pkg_present_at"`
FlowPkgRealPresent *gtime.Time `orm:"flow_pkg_real_present_at"`
FlowPkgEndAt *gtime.Time `orm:"flow_pkg_end_at"`
DataServiceStatus int `orm:"data_service_status"`
PackageTotalFlowMb float64 `orm:"package_total_flow_mb"`
UsedFlowMb float64 `orm:"used_flow_mb"`
TrafficCutoffEn int `orm:"traffic_cutoff_status"`
TrafficCutoffThr float64 `orm:"traffic_cutoff_threshold"`
SmsServiceStatus int `orm:"sms_service_status"`
PackageTotalSms int `orm:"package_total_sms"`
UsedSms int `orm:"used_sms"`
VoiceServiceStatus int `orm:"voice_service_status"`
PackageTotalVoice int `orm:"package_total_voice"`
UsedVoice int `orm:"used_voice"`
RoamServiceStatus int `orm:"roam_service_status"`
PkgTotalRoamFlowMb float64 `orm:"package_total_roam_flow_mb"`
UsedRoamFlowMb float64 `orm:"used_roam_flow_mb"`
TenantId string `orm:"tenant_id"`
CreatedDept int64 `orm:"created_dept"`
UpdatedBy int64 `orm:"updated_by"`
UpdatedAt *gtime.Time `orm:"updated_at"`
}
type SimCardBindPkg struct {
Id int64 `orm:"id"`
BatchNo string `orm:"batch_no"`
Iccid string `orm:"iccid"`
Msisdn string `orm:"msisdn"`
DeptId int64 `orm:"dept_id"`
PackageType int `orm:"package_type"`
PackageCode string `orm:"package_code"`
PreviousPackageCode string `orm:"previous_package_code"`
BusinessType int `orm:"business_type"`
EffectiveStatus int `orm:"effective_status"`
HandleTime *gtime.Time `orm:"handle_time"`
EffectiveTime *gtime.Time `orm:"effective_time"`
ExpectedExpireTime *gtime.Time `orm:"expected_expire_time"`
ActualExpireTime *gtime.Time `orm:"actual_expire_time"`
DurationMonths int `orm:"duration_months"`
GiftDurationMonths int `orm:"gift_duration_months"`
OrderCode string `orm:"order_code"`
SubscriptionNo string `orm:"subscription_no"`
Remark string `orm:"remark"`
TenantId string `orm:"tenant_id"`
CreatedDept int64 `orm:"created_dept"`
CreatedBy int64 `orm:"created_by"`
CreatedAt *gtime.Time `orm:"created_at"`
UpdatedBy int64 `orm:"updated_by"`
UpdatedAt *gtime.Time `orm:"updated_at"`
}
type SimBindPackageLogs struct {
Id int64 `orm:"id"`
SubscriptionNo string `orm:"subscription_no"`
BatchNo string `orm:"batch_no"`
Iccid string `orm:"iccid"`
Msisdn string `orm:"msisdn"`
DeptId int64 `orm:"dept_id"`
PackageType int `orm:"package_type"`
PackageCode string `orm:"package_code"`
PreviousPackageCod string `orm:"previous_package_code"`
BusinessType int `orm:"business_type"`
EffectiveStatus int `orm:"effective_status"`
HandleTime *gtime.Time `orm:"handle_time"`
EffectiveTime *gtime.Time `orm:"effective_time"`
ExpectedExpireTime *gtime.Time `orm:"expected_expire_time"`
ActualExpireTime *gtime.Time `orm:"actual_expire_time"`
DurationMonths int `orm:"duration_months"`
GiftDurationMonths int `orm:"gift_duration_months"`
OrderCode string `orm:"order_code"`
Remark string `orm:"remark"`
TenantId string `orm:"tenant_id"`
CreatedDept int64 `orm:"created_dept"`
CreatedBy int64 `orm:"created_by"`
CreatedAt *gtime.Time `orm:"created_at"`
UpdatedBy int64 `orm:"updated_by"`
UpdatedAt *gtime.Time `orm:"updated_at"`
}
type FlowPackageInfo struct {
Id int64 `orm:"id"`
PackageCode string `orm:"package_code"`
PoolPackageCode int64 `orm:"pool_package_code"`
PackageName string `orm:"package_name"`
PackageType int `orm:"package_type"`
BillingMethod int `orm:"billing_method"`
FlowMb float64 `orm:"flow_mb"`
CostPrice float64 `orm:"cost_price"`
SysDefaultRatio float64 `orm:"sys_default_ratio"`
SysDefaultProfit float64 `orm:"sys_default_profit"`
RenewableDurationConfig *gjson.Json `orm:"renewable_duration_config"`
RenewablePackageCodes *gjson.Json `orm:"renewable_package_codes"`
ChangeablePackageCodes *gjson.Json `orm:"changeable_package_codes"`
TopupPackageCodes *gjson.Json `orm:"topup_package_codes"`
Enabled int `orm:"enabled"`
TenantId string `orm:"tenant_id"`
}
type PoolBindPackageLogs struct {
Id int64 `orm:"id"`
SubscriptionNo string `orm:"subscription_no"`
BatchNo string `orm:"batch_no"`
PoolNo string `orm:"pool_no"`
DeptId int64 `orm:"dept_id"`
PackageType int `orm:"package_type"`
PackageCode string `orm:"package_code"`
PreviousPackageCode string `orm:"previous_package_code"`
BusinessType int `orm:"business_type"`
EffectiveStatus int `orm:"effective_status"`
HandleTime *gtime.Time `orm:"handle_time"`
EffectiveTime *gtime.Time `orm:"effective_time"`
ExpectedExpireTime *gtime.Time `orm:"expected_expire_time"`
ActualExpireTime *gtime.Time `orm:"actual_expire_time"`
DurationMonths int `orm:"duration_months"`
GiftDurationMonths int `orm:"gift_duration_months"`
OrderCode string `orm:"order_code"`
Remark string `orm:"remark"`
TenantId string `orm:"tenant_id"`
CreatedDept int64 `orm:"created_dept"`
CreatedBy int64 `orm:"created_by"`
CreatedAt *gtime.Time `orm:"created_at"`
UpdatedBy int64 `orm:"updated_by"`
UpdatedAt *gtime.Time `orm:"updated_at"`
}
type FlowPackagePrice struct {
Id int64 `orm:"id"`
TenantId string `orm:"tenant_id"`
DeptId int64 `orm:"dept_id"`
AgentScopeType int `orm:"agent_scope_type"`
TargetAgentId int64 `orm:"target_agent_id"`
PackageCode string `orm:"package_code"`
AgentCostRatio float64 `orm:"agent_cost_ratio"`
AgentCostProfit float64 `orm:"agent_cost_profit"`
}
type SysDeptRow struct {
DeptId int64 `orm:"dept_id"`
ParentId int64 `orm:"parent_id"`
DeptName string `orm:"dept_name"`
TenantId string `orm:"tenant_id"`
}
type BatchMainRow struct {
Id int64 `orm:"id"`
BatchNo string `orm:"batch_no"`
OrderSn string `orm:"order_sn"`
BatchType int `orm:"batch_type"`
BatchStatus int `orm:"batch_status"`
BatchAsyncStatus int `orm:"batch_async_status"`
SourceType int `orm:"source_type"`
SourceBatchNo string `orm:"source_batch_no"`
IsCrossDept int `orm:"is_cross_dept"`
TargetDeptId int64 `orm:"target_dept_id"`
DeptId int64 `orm:"dept_id"`
TotalCount int `orm:"total_count"`
ValidCount int `orm:"valid_count"`
SuccessCount int `orm:"success_count"`
FailCount int `orm:"fail_count"`
RunResult int `orm:"run_result"`
FailReason string `orm:"fail_reason"`
BatchInfo *gjson.Json `orm:"batch_info"`
StartTime *gtime.Time `orm:"start_time"`
EndTime *gtime.Time `orm:"end_time"`
TenantId string `orm:"tenant_id"`
CreatedDept int64 `orm:"created_dept"`
CreatedBy int64 `orm:"created_by"`
CreatedAt *gtime.Time `orm:"created_at"`
UpdatedBy int64 `orm:"updated_by"`
UpdatedAt *gtime.Time `orm:"updated_at"`
}
type BatchDetailRow struct {
Id int64 `orm:"id"`
BatchNo string `orm:"batch_no"`
BatchType int `orm:"batch_type"`
DetailStatus int `orm:"detail_status"`
BlankOutStatus int `orm:"blank_out_status"`
RowNo int `orm:"row_no"`
ItemId string `orm:"item_id"`
ErrorCode string `orm:"error_code"`
ErrorReason string `orm:"error_reason"`
Snapshot *gjson.Json `orm:"snapshot"`
TenantId string `orm:"tenant_id"`
CreatedDept int64 `orm:"created_dept"`
CreatedBy int64 `orm:"created_by"`
CreatedAt *gtime.Time `orm:"created_at"`
UpdatedBy int64 `orm:"updated_by"`
UpdatedAt *gtime.Time `orm:"updated_at"`
}
type SysOssRow struct {
Id int64 `orm:"id"`
TenantId string `orm:"tenant_id"`
FileName string `orm:"file_name"`
OriginalName string `orm:"original_name"`
FileSuffix string `orm:"file_suffix"`
Path string `orm:"path"`
Url string `orm:"url"`
Service string `orm:"service"`
Md5 string `orm:"md5"`
FileSize int64 `orm:"file_size"`
CreatedDept int64 `orm:"created_dept"`
CreatedBy int64 `orm:"created_by"`
UpdatedBy int64 `orm:"updated_by"`
}
type ResourceBatchDownloadRow struct {
Id int64 `orm:"id"`
BatchNo string `orm:"batch_no"`
TaskName string `orm:"task_name"`
ResourceType int `orm:"resource_type"`
ExportScene int `orm:"export_scene"`
TotalCount int `orm:"total_count"`
SuccessCount int `orm:"success_count"`
FailCount int `orm:"fail_count"`
DownloadStatus int `orm:"download_status"`
OssId int64 `orm:"oss_id"`
FileName string `orm:"file_name"`
FileExt string `orm:"file_ext"`
FileUrl string `orm:"file_url"`
FilePath string `orm:"file_path"`
FileSize int64 `orm:"file_size"`
FileMd5 string `orm:"file_md5"`
DownloadCount int `orm:"download_count"`
MaxDownloadCount int `orm:"max_download_count"`
DeptId int64 `orm:"dept_id"`
StartTime *gtime.Time `orm:"start_time"`
FinishTime *gtime.Time `orm:"finish_time"`
TenantId string `orm:"tenant_id"`
CreatedDept int64 `orm:"created_dept"`
CreatedBy int64 `orm:"created_by"`
UpdatedBy int64 `orm:"updated_by"`
}
// DB 默认从 g.DB() 取,避免和现有 repository 紧耦合。
func DB() gdb.DB {
return db()
}
func db() gdb.DB {
return g.DB()
}
func uniqueStrings(in []string) []string {
if len(in) == 0 {
return nil
}
seen := make(map[string]struct{}, len(in))
out := make([]string, 0, len(in))
for _, v := range in {
v = strings.TrimSpace(v)
if v == "" {
continue
}
if _, ok := seen[v]; ok {
continue
}
seen[v] = struct{}{}
out = append(out, v)
}
return out
}
// RoundAmount 四舍五入到分(导出以便 service 层复用)。
func RoundAmount(value float64) float64 {
return roundAmount(value)
}
func roundAmount(value float64) float64 {
if value < 0 {
return 0
}
return float64(int(value*100+0.5)) / 100
}
// RenewableDurationOptions 解析套餐的可续费时长配置。
func RenewableDurationOptions(jsonValue *gjson.Json) ([]int, error) {
return renewableDurationOptions(jsonValue)
}
func renewableDurationOptions(jsonValue *gjson.Json) ([]int, error) {
if jsonValue == nil || jsonValue.IsNil() {
return nil, errRenewDurationEmpty
}
values := jsonValue.Interfaces()
out := make([]int, 0, len(values))
seen := make(map[int]struct{}, len(values))
for _, raw := range values {
var month int
switch v := raw.(type) {
case int:
month = v
case int32:
month = int(v)
case int64:
month = int(v)
case float32:
month = int(v)
case float64:
month = int(v)
case json.Number:
n, err := v.Int64()
if err != nil {
continue
}
month = int(n)
case string:
if t, err := time.Parse("2006-01-02", strings.TrimSpace(v)); err == nil {
// tolerate date strings, fall back to ignoring
_ = t
}
continue
default:
continue
}
if month <= 0 {
continue
}
if _, ok := seen[month]; ok {
continue
}
seen[month] = struct{}{}
out = append(out, month)
}
sort.Ints(out)
if len(out) == 0 {
return nil, errRenewDurationEmpty
}
return out, nil
}
// ContainsInt 检查切片中是否包含目标值。
func ContainsInt(values []int, target int) bool {
return containsInt(values, target)
}
func containsInt(values []int, target int) bool {
for _, v := range values {
if v == target {
return true
}
}
return false
}