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,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
|
||||
}
|
||||
Reference in New Issue
Block a user