393 lines
14 KiB
Go
393 lines
14 KiB
Go
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
|
||
}
|