448 lines
13 KiB
Go
448 lines
13 KiB
Go
package dwbg
|
||
|
||
import (
|
||
"encoding/json"
|
||
"os"
|
||
"path/filepath"
|
||
"strings"
|
||
"testing"
|
||
|
||
"tyapi-server/internal/domains/api/dto"
|
||
|
||
"go.uber.org/zap"
|
||
)
|
||
|
||
func TestEmptySinanReportMarshal(t *testing.T) {
|
||
params := dto.DWBG6A2CReq{
|
||
Name: "张三",
|
||
IDCard: "320321199102011152",
|
||
MobileNo: "13812345678",
|
||
}
|
||
|
||
report := emptySinanReport(params)
|
||
data, err := json.Marshal(report)
|
||
if err != nil {
|
||
t.Fatalf("序列化失败: %v", err)
|
||
}
|
||
|
||
var parsed map[string]interface{}
|
||
if err := json.Unmarshal(data, &parsed); err != nil {
|
||
t.Fatalf("反序列化失败: %v", err)
|
||
}
|
||
|
||
requiredModules := []string{
|
||
"baseInfo", "standLiveInfo", "riskPoint", "securityInfo", "antiFraudInfo",
|
||
"riskList", "applicationStatistics", "lendingStatistics", "performanceStatistics",
|
||
"overdueRecord", "creditDetail", "rentalBehavior", "riskSupervision", "judicialLeaseReport",
|
||
}
|
||
for _, module := range requiredModules {
|
||
if _, ok := parsed[module]; !ok {
|
||
t.Errorf("缺少顶层模块: %s", module)
|
||
}
|
||
}
|
||
|
||
antiFraud, ok := parsed["antiFraudInfo"].(map[string]interface{})
|
||
if !ok {
|
||
t.Fatal("antiFraudInfo 类型错误")
|
||
}
|
||
for _, key := range []string{"moneyLaundering", "deceiver", "gamblerPlayer", "gamblerBanker"} {
|
||
if _, exists := antiFraud[key]; !exists {
|
||
t.Errorf("antiFraudInfo 缺少键: %s", key)
|
||
}
|
||
}
|
||
|
||
rental, ok := parsed["rentalBehavior"].(map[string]interface{})
|
||
if !ok {
|
||
t.Fatal("rentalBehavior 类型错误")
|
||
}
|
||
if len(rental) != len(rentalBehaviorFieldNames) {
|
||
t.Errorf("rentalBehavior 字段数 = %d, want %d", len(rental), len(rentalBehaviorFieldNames))
|
||
}
|
||
}
|
||
|
||
func TestTransformToSinanReportAllNil(t *testing.T) {
|
||
params := dto.DWBG6A2CReq{
|
||
Name: "张三",
|
||
IDCard: "320321199102011152",
|
||
MobileNo: "13812345678",
|
||
}
|
||
|
||
apiData := map[string]interface{}{
|
||
"YYSY35TA": nil,
|
||
"YYSYE7V5": nil,
|
||
"YYSYH6F3": nil,
|
||
"YYSYP0T4": nil,
|
||
"FLXGDEA9": nil,
|
||
"FLXG8B4D": nil,
|
||
"FLXG7E8F": nil,
|
||
"JRZQ5E9F": nil,
|
||
"JRZQ1D09": nil,
|
||
}
|
||
|
||
report := transformToSinanReport(apiData, params, zap.NewNop())
|
||
if _, err := json.Marshal(report); err != nil {
|
||
t.Fatalf("全 nil 数据源仍应可序列化: %v", err)
|
||
}
|
||
}
|
||
|
||
func TestTransformToSinanReportWithMockData(t *testing.T) {
|
||
params := dto.DWBG6A2CReq{
|
||
Name: "黄春丽",
|
||
IDCard: "452621197903185522",
|
||
MobileNo: "13907764404",
|
||
}
|
||
|
||
apiData := map[string]interface{}{
|
||
"YYSYH6F3": map[string]interface{}{
|
||
"result": "0",
|
||
"sex": "女",
|
||
"address": "广西壮族自治区百色地区百色市",
|
||
"channel": "cmcc",
|
||
},
|
||
"YYSYE7V5": map[string]interface{}{
|
||
"status": 0,
|
||
"channel": "cmcc",
|
||
},
|
||
"YYSY35TA": map[string]interface{}{
|
||
"prov": "广西壮族自治区",
|
||
"city": "南宁",
|
||
"name": "中国移动",
|
||
},
|
||
"YYSYP0T4": map[string]interface{}{
|
||
"time": "[24,-1)",
|
||
},
|
||
"FLXG8B4D": map[string]interface{}{
|
||
"gamblerBanker": "A",
|
||
},
|
||
"FLXGDEA9": map[string]interface{}{
|
||
"level": "A1,C3",
|
||
},
|
||
"JRZQ5E9F": map[string]interface{}{
|
||
"xyp_cpl0001": "2",
|
||
"xyp_cpl0007": "2",
|
||
"xyp_cpl0008": "1",
|
||
"xyp_cpl0011": "2",
|
||
"xyp_cpl0012": "2",
|
||
"xyp_cpl0013": "3",
|
||
"xyp_cpl0044": "1",
|
||
"xyp_cpl0074": "0.56",
|
||
"xyp_model_score_mid": "500",
|
||
},
|
||
"JRZQ1D09": map[string]interface{}{
|
||
"m12": map[string]interface{}{
|
||
"id": map[string]interface{}{"allnum": "7", "orgnum": "1", "tot_mons": "16"},
|
||
"cell": map[string]interface{}{"allnum": "7", "orgnum": "1", "tot_mons": "16"},
|
||
},
|
||
"idcard_relation_phone": 1,
|
||
"phone_relation_idard": 0,
|
||
},
|
||
}
|
||
|
||
report := transformToSinanReport(apiData, params, zap.NewNop())
|
||
|
||
standLive := report["standLiveInfo"].(map[string]interface{})
|
||
if standLive["finalAuthResult"] != "0" || standLive["verification"] != "0" {
|
||
t.Errorf("standLiveInfo 三要素映射错误: %+v", standLive)
|
||
}
|
||
if standLive["inTime"] != "24" {
|
||
t.Errorf("inTime = %v, want 24", standLive["inTime"])
|
||
}
|
||
|
||
security := report["securityInfo"].(map[string]interface{})
|
||
if security["front"] != 1 || security["escape"] != 0 || security["drug"] != 1 {
|
||
t.Errorf("securityInfo 解析错误: %+v", security)
|
||
}
|
||
|
||
antiFraud := report["antiFraudInfo"].(map[string]interface{})
|
||
if antiFraud["gamblerBanker"] != "A" {
|
||
t.Errorf("antiFraudInfo.gamblerBanker = %v", antiFraud["gamblerBanker"])
|
||
}
|
||
|
||
riskList := report["riskList"].(map[string]interface{})
|
||
if riskList["creditLeaseRisk"] != 1 {
|
||
t.Errorf("creditLeaseRisk = %v, want 1", riskList["creditLeaseRisk"])
|
||
}
|
||
if riskList["vehicleLeaseViolation"] != 1 {
|
||
t.Errorf("vehicleLeaseViolation = %v, want 1", riskList["vehicleLeaseViolation"])
|
||
}
|
||
if riskList["highRiskArea"] != 0 {
|
||
t.Errorf("highRiskArea = %v, want 0", riskList["highRiskArea"])
|
||
}
|
||
|
||
riskPoint := report["riskPoint"].(map[string]interface{})
|
||
if riskPoint["antiFraudRisk"] != 1 {
|
||
t.Errorf("antiFraudRisk = %v, want 1", riskPoint["antiFraudRisk"])
|
||
}
|
||
if riskPoint["judicialCase"] != 0 {
|
||
t.Errorf("judicialCase = %v, want 0", riskPoint["judicialCase"])
|
||
}
|
||
|
||
perf := report["performanceStatistics"].(map[string]interface{})
|
||
if perf["serialVersionUID"] != 1 {
|
||
t.Errorf("serialVersionUID = %v, want 1", perf["serialVersionUID"])
|
||
}
|
||
}
|
||
|
||
func TestMapYYSYH6F3StandLive(t *testing.T) {
|
||
cases := []struct {
|
||
result, wantFinal, wantVerify string
|
||
}{
|
||
{"0", "0", "0"},
|
||
{"1", "1", "1"},
|
||
{"2", "1", "-1"},
|
||
{"", "1", "-1"},
|
||
}
|
||
for _, tc := range cases {
|
||
final, verify := mapYYSYH6F3StandLive(tc.result)
|
||
if final != tc.wantFinal || verify != tc.wantVerify {
|
||
t.Errorf("result=%q got (%s,%s) want (%s,%s)", tc.result, final, verify, tc.wantFinal, tc.wantVerify)
|
||
}
|
||
}
|
||
}
|
||
|
||
func TestParseSecurityInfoLevel(t *testing.T) {
|
||
info := parseSecurityInfoLevel("A,C3")
|
||
if info["escape"] != 1 || info["front"] != 0 || info["drug"] != 1 {
|
||
t.Fatalf("A,C3 => %+v", info)
|
||
}
|
||
info = parseSecurityInfoLevel("A1")
|
||
if info["front"] != 1 || info["escape"] != 0 {
|
||
t.Fatalf("A1 => %+v", info)
|
||
}
|
||
}
|
||
|
||
func TestIndustryBlacklistHit(t *testing.T) {
|
||
if !industryBlacklistHit("D1,B") {
|
||
t.Fatal("D1 should hit industry blacklist")
|
||
}
|
||
if industryBlacklistHit("A1,C3") {
|
||
t.Fatal("A1,C3 should not hit industry blacklist")
|
||
}
|
||
}
|
||
|
||
func TestReportNoNullValues(t *testing.T) {
|
||
params := dto.DWBG6A2CReq{
|
||
Name: "张三",
|
||
IDCard: "320321199102011152",
|
||
MobileNo: "13812345678",
|
||
}
|
||
apiData := map[string]interface{}{
|
||
"FLXG7E8F": map[string]interface{}{
|
||
"judicial_data": map[string]interface{}{
|
||
"breachCaseList": []interface{}{},
|
||
"consumptionRestrictionList": []interface{}{},
|
||
"lawsuitStat": map[string]interface{}{
|
||
"count": map[string]interface{}{
|
||
"count_beigao": 0,
|
||
"larq_stat": "",
|
||
},
|
||
"civil": map[string]interface{}{
|
||
"cases": []interface{}{},
|
||
"count": map[string]interface{}{"count_total": 0},
|
||
},
|
||
},
|
||
},
|
||
},
|
||
}
|
||
report := transformToSinanReport(apiData, params, zap.NewNop())
|
||
cleaned, ok := stripNullValues(report).(map[string]interface{})
|
||
if !ok {
|
||
t.Fatal("stripNullValues failed")
|
||
}
|
||
if reportContainsNull(cleaned) {
|
||
t.Fatal("report still contains null after strip")
|
||
}
|
||
data, err := json.Marshal(cleaned)
|
||
if err != nil {
|
||
t.Fatalf("marshal failed: %v", err)
|
||
}
|
||
if strings.Contains(string(data), "null") {
|
||
t.Fatalf("JSON contains null: %s", string(data))
|
||
}
|
||
}
|
||
|
||
func TestBuildJudicialLeaseReportWithCases(t *testing.T) {
|
||
apiData := map[string]interface{}{
|
||
"FLXG7E8F": map[string]interface{}{
|
||
"judicial_data": map[string]interface{}{
|
||
"breachCaseList": []interface{}{},
|
||
"consumptionRestrictionList": []interface{}{},
|
||
"lawsuitStat": map[string]interface{}{
|
||
"count": map[string]interface{}{
|
||
"count_total": 1,
|
||
"count_beigao": 1,
|
||
"larq_stat": "2026(1)",
|
||
"ay_stat": "民事(1)",
|
||
},
|
||
"civil": map[string]interface{}{
|
||
"cases": []interface{}{
|
||
map[string]interface{}{
|
||
"c_ah": "(2019)桂0103民初5129号",
|
||
"n_ssdw": "原告",
|
||
"n_ajjzjd": "已结案",
|
||
"n_ajlx": "民事一审",
|
||
"c_dsrxx": []interface{}{
|
||
map[string]interface{}{
|
||
"c_mc": "黄春丽",
|
||
"n_ssdw": "原告",
|
||
"n_dsrlx": "自然人",
|
||
},
|
||
},
|
||
},
|
||
},
|
||
"count": map[string]interface{}{
|
||
"count_total": 1,
|
||
"count_beigao": 1,
|
||
},
|
||
},
|
||
"preservation": map[string]interface{}{
|
||
"cases": []interface{}{},
|
||
"count": map[string]interface{}{"count_total": 1},
|
||
},
|
||
"implement": map[string]interface{}{
|
||
"cases": []interface{}{},
|
||
"count": map[string]interface{}{"count_total": 0},
|
||
},
|
||
},
|
||
},
|
||
},
|
||
}
|
||
jlr := buildJudicialLeaseReport(apiData)
|
||
courtInfo := jlr["courtInfo"].(map[string]interface{})
|
||
if courtInfo["civilCasesCount"] != 1 {
|
||
t.Fatalf("civilCasesCount = %v", courtInfo["civilCasesCount"])
|
||
}
|
||
if courtInfo["preservationCasesCount"] != 1 {
|
||
t.Fatalf("preservationCasesCount = %v", courtInfo["preservationCasesCount"])
|
||
}
|
||
newMult := courtInfo["newMultCourtInfo"].(map[string]interface{})
|
||
civilCases, ok := newMult["civilCases"].([]interface{})
|
||
if !ok || len(civilCases) != 1 {
|
||
t.Fatalf("civilCases missing or empty: %+v", newMult["civilCases"])
|
||
}
|
||
if _, has := newMult["preservationCases"]; has {
|
||
t.Fatal("preservationCases list should be omitted when empty")
|
||
}
|
||
overview := jlr["caseOverviewInfo"].(map[string]interface{})
|
||
if overview["beigaoTotalCasesCounts"] != 1 {
|
||
t.Fatalf("beigaoTotalCasesCounts = %v", overview["beigaoTotalCasesCounts"])
|
||
}
|
||
}
|
||
|
||
func TestT2SampleJudicialAndSecurityMapping(t *testing.T) {
|
||
base := filepath.Join("..", "..", "..", "..", "..", "..", "..", "司南报告")
|
||
load := func(name string) map[string]interface{} {
|
||
b, err := os.ReadFile(filepath.Join(base, name))
|
||
if err != nil {
|
||
t.Fatalf("read %s: %v", name, err)
|
||
}
|
||
var m map[string]interface{}
|
||
if err := json.Unmarshal(b, &m); err != nil {
|
||
t.Fatalf("unmarshal %s: %v", name, err)
|
||
}
|
||
return m
|
||
}
|
||
|
||
params := dto.DWBG6A2CReq{
|
||
Name: "何志勇",
|
||
IDCard: "45212719910201152X",
|
||
MobileNo: "18277111590",
|
||
}
|
||
apiData := map[string]interface{}{
|
||
"FLXG7E8F": load("t2-1.json"),
|
||
"FLXGDEA9": load("t2-2.json"),
|
||
}
|
||
report := transformToSinanReport(apiData, params, zap.NewNop())
|
||
|
||
jlr := report["judicialLeaseReport"].(map[string]interface{})
|
||
courtInfo := jlr["courtInfo"].(map[string]interface{})
|
||
if courtInfo["criminalCasesCount"] != 4 {
|
||
t.Fatalf("criminalCasesCount = %v, want 4", courtInfo["criminalCasesCount"])
|
||
}
|
||
newMult := courtInfo["newMultCourtInfo"].(map[string]interface{})
|
||
criminalCases, ok := newMult["criminalCases"].([]interface{})
|
||
if !ok || len(criminalCases) != 4 {
|
||
t.Fatalf("criminalCases = %v, want 4 items", newMult["criminalCases"])
|
||
}
|
||
overview := jlr["caseOverviewInfo"].(map[string]interface{})
|
||
if overview["beigaoTotalCasesCounts"] != 2 {
|
||
t.Fatalf("beigaoTotalCasesCounts = %v, want 2", overview["beigaoTotalCasesCounts"])
|
||
}
|
||
if overview["leastCaseTime"] != "2019(2)" {
|
||
t.Fatalf("leastCaseTime = %v, want 2019(2)", overview["leastCaseTime"])
|
||
}
|
||
|
||
security := report["securityInfo"].(map[string]interface{})
|
||
if security["escape"] != 1 || security["icase"] != 1 {
|
||
t.Fatalf("securityInfo A => %+v", security)
|
||
}
|
||
if security["ikey"] != 1 {
|
||
t.Fatalf("securityInfo D5 => ikey=%v", security["ikey"])
|
||
}
|
||
|
||
riskPoint := report["riskPoint"].(map[string]interface{})
|
||
if riskPoint["judicialRisk"] != 1 || riskPoint["legalCasesFlag"] != 1 {
|
||
t.Fatalf("riskPoint judicial flags = %+v", riskPoint)
|
||
}
|
||
if riskPoint["securityRisk"] != 1 {
|
||
t.Fatalf("securityRisk = %v, want 1", riskPoint["securityRisk"])
|
||
}
|
||
}
|
||
|
||
func TestT2SampleWithDataWrapper(t *testing.T) {
|
||
base := filepath.Join("..", "..", "..", "..", "..", "..", "..", "司南报告")
|
||
load := func(name string) map[string]interface{} {
|
||
b, err := os.ReadFile(filepath.Join(base, name))
|
||
if err != nil {
|
||
t.Fatalf("read %s: %v", name, err)
|
||
}
|
||
var m map[string]interface{}
|
||
if err := json.Unmarshal(b, &m); err != nil {
|
||
t.Fatalf("unmarshal %s: %v", name, err)
|
||
}
|
||
return m
|
||
}
|
||
|
||
params := dto.DWBG6A2CReq{
|
||
Name: "何志勇",
|
||
IDCard: "45212719910201152X",
|
||
MobileNo: "18277111590",
|
||
}
|
||
apiData := map[string]interface{}{
|
||
"FLXG7E8F": map[string]interface{}{"data": load("t2-1.json")},
|
||
"FLXGDEA9": map[string]interface{}{"data": load("t2-2.json")},
|
||
}
|
||
report := transformToSinanReport(apiData, params, zap.NewNop())
|
||
|
||
jlr := report["judicialLeaseReport"].(map[string]interface{})
|
||
courtInfo := jlr["courtInfo"].(map[string]interface{})
|
||
if courtInfo["criminalCasesCount"] != 4 {
|
||
t.Fatalf("wrapped criminalCasesCount = %v, want 4", courtInfo["criminalCasesCount"])
|
||
}
|
||
security := report["securityInfo"].(map[string]interface{})
|
||
if security["escape"] != 1 || security["ikey"] != 1 {
|
||
t.Fatalf("wrapped securityInfo = %+v", security)
|
||
}
|
||
riskList := report["riskList"].(map[string]interface{})
|
||
if riskList["industryBlacklist"] != 1 {
|
||
t.Fatalf("wrapped industryBlacklist = %v, want 1", riskList["industryBlacklist"])
|
||
}
|
||
}
|
||
|
||
func TestM1PlusCountCaps(t *testing.T) {
|
||
apiData := map[string]interface{}{
|
||
"JRZQ5E9F": map[string]interface{}{
|
||
"xyp_cpl0029": "1",
|
||
"xyp_cpl0030": "1",
|
||
"xyp_cpl0031": "1",
|
||
},
|
||
}
|
||
record := buildOverdueRecord(apiData)
|
||
if record["m1PlusCountLast6Months"] != 3 {
|
||
t.Fatalf("6m cap = %v", record["m1PlusCountLast6Months"])
|
||
}
|
||
if record["m1PlusCountLast12Months"] != 3 {
|
||
t.Fatalf("12m cap = %v", record["m1PlusCountLast12Months"])
|
||
}
|
||
}
|