346 lines
12 KiB
Python
346 lines
12 KiB
Python
"""
|
||
验证模板字段同步结果
|
||
检查 input_data、template_code 和字段关联关系是否正确
|
||
"""
|
||
import os
|
||
import json
|
||
import pymysql
|
||
from typing import Dict, List
|
||
|
||
# 数据库连接配置
|
||
DB_CONFIG = {
|
||
'host': os.getenv('DB_HOST', '152.136.177.240'),
|
||
'port': int(os.getenv('DB_PORT', 5012)),
|
||
'user': os.getenv('DB_USER', 'finyx'),
|
||
'password': os.getenv('DB_PASSWORD', '6QsGK6MpePZDE57Z'),
|
||
'database': os.getenv('DB_NAME', 'finyx'),
|
||
'charset': 'utf8mb4'
|
||
}
|
||
|
||
TENANT_ID = 615873064429507639
|
||
|
||
|
||
def verify_template_configs(conn):
|
||
"""验证模板配置的 input_data 和 template_code"""
|
||
cursor = conn.cursor(pymysql.cursors.DictCursor)
|
||
|
||
print("="*80)
|
||
print("验证模板配置")
|
||
print("="*80)
|
||
|
||
sql = """
|
||
SELECT id, name, template_code, input_data, parent_id
|
||
FROM f_polic_file_config
|
||
WHERE tenant_id = %s
|
||
ORDER BY parent_id, name
|
||
"""
|
||
cursor.execute(sql, (TENANT_ID,))
|
||
configs = cursor.fetchall()
|
||
|
||
print(f"\n共 {len(configs)} 个模板配置\n")
|
||
|
||
# 统计
|
||
has_template_code = 0
|
||
has_input_data = 0
|
||
has_both = 0
|
||
missing_both = 0
|
||
|
||
# 文件节点(有 template_code 的)
|
||
file_nodes = []
|
||
# 目录节点(没有 template_code 的)
|
||
dir_nodes = []
|
||
|
||
for config in configs:
|
||
template_code = config.get('template_code')
|
||
input_data = config.get('input_data')
|
||
|
||
if template_code:
|
||
has_template_code += 1
|
||
file_nodes.append(config)
|
||
else:
|
||
dir_nodes.append(config)
|
||
|
||
if input_data:
|
||
has_input_data += 1
|
||
try:
|
||
input_data_dict = json.loads(input_data) if isinstance(input_data, str) else input_data
|
||
if isinstance(input_data_dict, dict) and input_data_dict.get('template_code'):
|
||
has_both += 1
|
||
except:
|
||
pass
|
||
|
||
if not template_code and not input_data:
|
||
missing_both += 1
|
||
|
||
print("统计信息:")
|
||
print(f" 文件节点(有 template_code): {len(file_nodes)} 个")
|
||
print(f" 目录节点(无 template_code): {len(dir_nodes)} 个")
|
||
print(f" 有 input_data: {has_input_data} 个")
|
||
print(f" 同时有 template_code 和 input_data: {has_both} 个")
|
||
print(f" 两者都没有: {missing_both} 个")
|
||
|
||
# 检查文件节点的 input_data
|
||
print("\n文件节点 input_data 检查:")
|
||
missing_input_data = []
|
||
for config in file_nodes:
|
||
input_data = config.get('input_data')
|
||
if not input_data:
|
||
missing_input_data.append(config)
|
||
else:
|
||
try:
|
||
input_data_dict = json.loads(input_data) if isinstance(input_data, str) else input_data
|
||
if not isinstance(input_data_dict, dict) or 'template_code' not in input_data_dict:
|
||
missing_input_data.append(config)
|
||
except:
|
||
missing_input_data.append(config)
|
||
|
||
if missing_input_data:
|
||
print(f" ⚠ 有 {len(missing_input_data)} 个文件节点缺少或格式错误的 input_data:")
|
||
for config in missing_input_data[:10]: # 只显示前10个
|
||
print(f" - {config['name']} (ID: {config['id']})")
|
||
if len(missing_input_data) > 10:
|
||
print(f" ... 还有 {len(missing_input_data) - 10} 个")
|
||
else:
|
||
print(" ✓ 所有文件节点都有正确的 input_data")
|
||
|
||
cursor.close()
|
||
return {
|
||
'total': len(configs),
|
||
'file_nodes': len(file_nodes),
|
||
'dir_nodes': len(dir_nodes),
|
||
'has_input_data': has_input_data,
|
||
'has_both': has_both,
|
||
'missing_input_data': len(missing_input_data)
|
||
}
|
||
|
||
|
||
def verify_field_relations(conn):
|
||
"""验证字段关联关系"""
|
||
cursor = conn.cursor(pymysql.cursors.DictCursor)
|
||
|
||
print("\n" + "="*80)
|
||
print("验证字段关联关系")
|
||
print("="*80)
|
||
|
||
# 获取所有文件节点的字段关联
|
||
sql = """
|
||
SELECT
|
||
fc.id as file_id,
|
||
fc.name as file_name,
|
||
fc.template_code,
|
||
COUNT(ff.id) as field_count,
|
||
SUM(CASE WHEN f.field_type = 1 THEN 1 ELSE 0 END) as input_field_count,
|
||
SUM(CASE WHEN f.field_type = 2 THEN 1 ELSE 0 END) as output_field_count
|
||
FROM f_polic_file_config fc
|
||
LEFT JOIN f_polic_file_field ff ON fc.id = ff.file_id AND ff.tenant_id = fc.tenant_id
|
||
LEFT JOIN f_polic_field f ON ff.filed_id = f.id AND f.tenant_id = fc.tenant_id
|
||
WHERE fc.tenant_id = %s AND fc.template_code IS NOT NULL
|
||
GROUP BY fc.id, fc.name, fc.template_code
|
||
ORDER BY fc.name
|
||
"""
|
||
cursor.execute(sql, (TENANT_ID,))
|
||
relations = cursor.fetchall()
|
||
|
||
print(f"\n共 {len(relations)} 个文件节点有字段关联\n")
|
||
|
||
# 统计
|
||
has_relations = 0
|
||
no_relations = 0
|
||
has_input_fields = 0
|
||
has_output_fields = 0
|
||
|
||
no_relation_templates = []
|
||
|
||
for rel in relations:
|
||
field_count = rel['field_count'] or 0
|
||
input_count = rel['input_field_count'] or 0
|
||
output_count = rel['output_field_count'] or 0
|
||
|
||
if field_count > 0:
|
||
has_relations += 1
|
||
if input_count > 0:
|
||
has_input_fields += 1
|
||
if output_count > 0:
|
||
has_output_fields += 1
|
||
else:
|
||
no_relations += 1
|
||
no_relation_templates.append(rel)
|
||
|
||
print("统计信息:")
|
||
print(f" 有字段关联: {has_relations} 个")
|
||
print(f" 无字段关联: {no_relations} 个")
|
||
print(f" 有输入字段: {has_input_fields} 个")
|
||
print(f" 有输出字段: {has_output_fields} 个")
|
||
|
||
if no_relation_templates:
|
||
print(f"\n ⚠ 有 {len(no_relation_templates)} 个文件节点没有字段关联:")
|
||
for rel in no_relation_templates[:10]:
|
||
print(f" - {rel['file_name']} (code: {rel['template_code']})")
|
||
if len(no_relation_templates) > 10:
|
||
print(f" ... 还有 {len(no_relation_templates) - 10} 个")
|
||
else:
|
||
print("\n ✓ 所有文件节点都有字段关联")
|
||
|
||
# 显示详细的关联信息(前10个)
|
||
print("\n字段关联详情(前10个):")
|
||
for rel in relations[:10]:
|
||
print(f"\n {rel['file_name']} (code: {rel['template_code']})")
|
||
print(f" 总字段数: {rel['field_count']}")
|
||
print(f" 输入字段: {rel['input_field_count']}")
|
||
print(f" 输出字段: {rel['output_field_count']}")
|
||
|
||
cursor.close()
|
||
return {
|
||
'total': len(relations),
|
||
'has_relations': has_relations,
|
||
'no_relations': no_relations,
|
||
'has_input_fields': has_input_fields,
|
||
'has_output_fields': has_output_fields
|
||
}
|
||
|
||
|
||
def verify_input_data_structure(conn):
|
||
"""验证 input_data 的结构"""
|
||
cursor = conn.cursor(pymysql.cursors.DictCursor)
|
||
|
||
print("\n" + "="*80)
|
||
print("验证 input_data 结构")
|
||
print("="*80)
|
||
|
||
sql = """
|
||
SELECT id, name, template_code, input_data
|
||
FROM f_polic_file_config
|
||
WHERE tenant_id = %s AND template_code IS NOT NULL AND input_data IS NOT NULL
|
||
"""
|
||
cursor.execute(sql, (TENANT_ID,))
|
||
configs = cursor.fetchall()
|
||
|
||
print(f"\n检查 {len(configs)} 个有 input_data 的文件节点\n")
|
||
|
||
correct_structure = 0
|
||
incorrect_structure = 0
|
||
incorrect_items = []
|
||
|
||
for config in configs:
|
||
try:
|
||
input_data = json.loads(config['input_data']) if isinstance(config['input_data'], str) else config['input_data']
|
||
|
||
if not isinstance(input_data, dict):
|
||
incorrect_structure += 1
|
||
incorrect_items.append({
|
||
'name': config['name'],
|
||
'reason': 'input_data 不是字典格式'
|
||
})
|
||
continue
|
||
|
||
# 检查必需字段
|
||
required_fields = ['template_code', 'business_type']
|
||
missing_fields = [f for f in required_fields if f not in input_data]
|
||
|
||
if missing_fields:
|
||
incorrect_structure += 1
|
||
incorrect_items.append({
|
||
'name': config['name'],
|
||
'reason': f'缺少字段: {", ".join(missing_fields)}'
|
||
})
|
||
continue
|
||
|
||
# 检查 template_code 是否匹配
|
||
if input_data.get('template_code') != config.get('template_code'):
|
||
incorrect_structure += 1
|
||
incorrect_items.append({
|
||
'name': config['name'],
|
||
'reason': f"template_code 不匹配: input_data中为 '{input_data.get('template_code')}', 字段中为 '{config.get('template_code')}'"
|
||
})
|
||
continue
|
||
|
||
correct_structure += 1
|
||
|
||
except json.JSONDecodeError as e:
|
||
incorrect_structure += 1
|
||
incorrect_items.append({
|
||
'name': config['name'],
|
||
'reason': f'JSON解析错误: {str(e)}'
|
||
})
|
||
except Exception as e:
|
||
incorrect_structure += 1
|
||
incorrect_items.append({
|
||
'name': config['name'],
|
||
'reason': f'其他错误: {str(e)}'
|
||
})
|
||
|
||
print(f" 结构正确: {correct_structure} 个")
|
||
print(f" 结构错误: {incorrect_structure} 个")
|
||
|
||
if incorrect_items:
|
||
print("\n 错误详情:")
|
||
for item in incorrect_items[:10]:
|
||
print(f" - {item['name']}: {item['reason']}")
|
||
if len(incorrect_items) > 10:
|
||
print(f" ... 还有 {len(incorrect_items) - 10} 个错误")
|
||
else:
|
||
print("\n ✓ 所有 input_data 结构都正确")
|
||
|
||
cursor.close()
|
||
return {
|
||
'correct': correct_structure,
|
||
'incorrect': incorrect_structure
|
||
}
|
||
|
||
|
||
def main():
|
||
"""主函数"""
|
||
print("="*80)
|
||
print("验证模板字段同步结果")
|
||
print("="*80)
|
||
|
||
try:
|
||
conn = pymysql.connect(**DB_CONFIG)
|
||
print("✓ 数据库连接成功\n")
|
||
except Exception as e:
|
||
print(f"✗ 数据库连接失败: {e}")
|
||
return
|
||
|
||
try:
|
||
# 验证模板配置
|
||
config_stats = verify_template_configs(conn)
|
||
|
||
# 验证字段关联
|
||
relation_stats = verify_field_relations(conn)
|
||
|
||
# 验证 input_data 结构
|
||
input_data_stats = verify_input_data_structure(conn)
|
||
|
||
# 总结
|
||
print("\n" + "="*80)
|
||
print("验证总结")
|
||
print("="*80)
|
||
print(f"模板配置:")
|
||
print(f" - 总模板数: {config_stats['total']}")
|
||
print(f" - 文件节点: {config_stats['file_nodes']}")
|
||
print(f" - 缺少 input_data: {config_stats['missing_input_data']} 个")
|
||
print(f"\n字段关联:")
|
||
print(f" - 有字段关联: {relation_stats['has_relations']} 个")
|
||
print(f" - 无字段关联: {relation_stats['no_relations']} 个")
|
||
print(f"\ninput_data 结构:")
|
||
print(f" - 正确: {input_data_stats['correct']} 个")
|
||
print(f" - 错误: {input_data_stats['incorrect']} 个")
|
||
|
||
# 总体评估
|
||
print("\n" + "="*80)
|
||
if (config_stats['missing_input_data'] == 0 and
|
||
relation_stats['no_relations'] == 0 and
|
||
input_data_stats['incorrect'] == 0):
|
||
print("✓ 所有验证通过!同步成功!")
|
||
else:
|
||
print("⚠ 发现一些问题,请检查上述详情")
|
||
|
||
finally:
|
||
conn.close()
|
||
print("\n数据库连接已关闭")
|
||
|
||
|
||
if __name__ == '__main__':
|
||
main()
|
||
|