package service import ( "encoding/json" "fmt" "strconv" "strings" "time" ) type dbAPN struct { APNName string `json:"apnName"` Status string `json:"status"` DiagnosisStatus string `json:"diagnosisStatus"` UsageBytes json.Number `json:"usageBytes"` ModifyTime string `json:"modifyTime"` OverUseDetails string `json:"overUseDetails"` ServiceUsageState string `json:"serviceUsageState"` PCCs []dbPCC `json:"pccs"` } type dbPCC struct { ServiceCode string `json:"serviceCode"` Name string `json:"name"` PolicyStatus string `json:"policyStatus"` ServiceUsageState string `json:"serviceUsageState"` ModifyTime string `json:"modifyTime"` } func parseAPNs(raw, fallbackName, fallbackStatus string, fallbackUsageKB float64, fallbackUsageBytes int64) []APN { var rows []dbAPN decoder := json.NewDecoder(strings.NewReader(raw)) decoder.UseNumber() if raw != "" && decoder.Decode(&rows) == nil { apns := make([]APN, 0, len(rows)) for _, row := range rows { usageBytes, _ := strconv.ParseFloat(row.UsageBytes.String(), 64) pccs := make([]PCC, 0, len(row.PCCs)) for _, pcc := range row.PCCs { pccs = append(pccs, PCC{ServiceCode: pcc.ServiceCode, Name: pcc.Name, PolicyStatus: pcc.PolicyStatus, ServiceUsageState: pcc.ServiceUsageState, ModifyTime: pcc.ModifyTime}) } apns = append(apns, APN{Name: row.APNName, Status: row.Status, DiagnosisStatus: row.DiagnosisStatus, UsageBytes: usageBytes, ModifyTime: row.ModifyTime, OverUseDetails: row.OverUseDetails, ServiceUsageState: row.ServiceUsageState, PCCs: pccs}) } return apns } usageBytes := float64(fallbackUsageBytes) if usageBytes == 0 && fallbackUsageKB > 0 { usageBytes = fallbackUsageKB * 1024 } if fallbackName == "" { return nil } return []APN{{Name: fallbackName, Status: fallbackStatus, UsageBytes: usageBytes}} } func apnsForDB(apns []APN) []map[string]interface{} { out := make([]map[string]interface{}, 0, len(apns)) for _, apn := range apns { out = append(out, map[string]interface{}{ "apnName": apn.Name, "status": apn.Status, "diagnosisStatus": apn.DiagnosisStatus, "usageBytes": int64(apn.UsageBytes), "modifyTime": apn.ModifyTime, "overUseDetails": apn.OverUseDetails, "serviceUsageState": apn.ServiceUsageState, "pccs": pccsForDB(apn.PCCs), }) } return out } func pccsForDB(pccs []PCC) []map[string]string { out := make([]map[string]string, 0, len(pccs)) for _, pcc := range pccs { out = append(out, map[string]string{ "serviceCode": pcc.ServiceCode, "name": pcc.Name, "policyStatus": pcc.PolicyStatus, "serviceUsageState": pcc.ServiceUsageState, "modifyTime": pcc.ModifyTime, }) } return out } func primaryAPN(card SIMCard) APN { for _, apn := range card.APNs { if apn.Status == "1" { return apn } } if len(card.APNs) > 0 { return card.APNs[0] } return APN{Name: "CMIOT", Status: "1", UsageBytes: card.MonthUsageKB * 1024} } func sourceRemark(carrier, packageCode, packageName string) string { return fmt.Sprintf("carrier=%s; package=%s; name=%s; channel=%s; supplier=%s", carrier, packageCode, packageName, generatedChanKey, generatedSupplierCode) } func mockMetadataFromRemark(remark string) (string, string, string) { values := map[string]string{} for _, part := range strings.Split(remark, ";") { key, value, ok := strings.Cut(strings.TrimSpace(part), "=") if ok { values[strings.ToLower(strings.TrimSpace(key))] = strings.TrimSpace(value) } } carrier := values["carrier"] if carrier == "" { carrier = "CMCC" } packageCode := values["package"] if packageCode == "" { packageCode = generatedPackageCode } packageName := values["name"] if packageName == "" { packageName = generatedPackageCode } return carrier, packageCode, packageName } func dbTimeToRFC3339(value string) string { if value == "" { return time.Now().Format(time.RFC3339) } if t, err := time.ParseInLocation("2006-01-02 15:04:05", value, time.Local); err == nil { return t.Format(time.RFC3339) } return value } func rfc3339ToDBTime(value string) string { if value == "" { return "" } for _, layout := range []string{time.RFC3339Nano, time.RFC3339, "2006-01-02 15:04:05"} { if t, err := time.ParseInLocation(layout, value, time.Local); err == nil { return t.Format("2006-01-02 15:04:05") } } return value }