ai-business-write/check_file_field_relations_comprehensive.py

497 lines
18 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
全面检查 f_polic_file_field 表的关联关系
重点检查输入字段field_type=1和输出字段field_type=2与模板的关联情况
"""
import pymysql
import os
import sys
from typing import Dict, List, Tuple
from collections import defaultdict
# 设置输出编码为UTF-8
if sys.platform == 'win32':
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
# 数据库连接配置
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 check_all_templates_field_relations(conn) -> Dict:
"""检查所有模板的字段关联情况"""
cursor = conn.cursor(pymysql.cursors.DictCursor)
print("\n" + "="*80)
print("1. 检查所有模板的字段关联情况")
print("="*80)
# 获取所有启用的模板
cursor.execute("""
SELECT id, name, template_code
FROM f_polic_file_config
WHERE tenant_id = %s AND state = 1
ORDER BY name
""", (TENANT_ID,))
templates = cursor.fetchall()
# 获取每个模板关联的字段(按类型分组)
cursor.execute("""
SELECT
fc.id AS template_id,
fc.name AS template_name,
f.id AS field_id,
f.name AS field_name,
f.filed_code AS field_code,
f.field_type
FROM f_polic_file_config fc
INNER JOIN f_polic_file_field fff ON fc.id = fff.file_id AND fc.tenant_id = fff.tenant_id
INNER JOIN f_polic_field f ON fff.filed_id = f.id AND fff.tenant_id = f.tenant_id
WHERE fc.tenant_id = %s
AND fc.state = 1
AND fff.state = 1
AND f.state = 1
ORDER BY fc.name, f.field_type, f.name
""", (TENANT_ID,))
relations = cursor.fetchall()
# 按模板分组统计
template_stats = {}
for template in templates:
template_stats[template['id']] = {
'template_id': template['id'],
'template_name': template['name'],
'template_code': template.get('template_code'),
'input_fields': [],
'output_fields': [],
'input_count': 0,
'output_count': 0
}
# 填充字段信息
for rel in relations:
template_id = rel['template_id']
if template_id in template_stats:
field_info = {
'field_id': rel['field_id'],
'field_name': rel['field_name'],
'field_code': rel['field_code'],
'field_type': rel['field_type']
}
if rel['field_type'] == 1:
template_stats[template_id]['input_fields'].append(field_info)
template_stats[template_id]['input_count'] += 1
elif rel['field_type'] == 2:
template_stats[template_id]['output_fields'].append(field_info)
template_stats[template_id]['output_count'] += 1
# 打印统计信息
print(f"\n共找到 {len(templates)} 个启用的模板\n")
templates_without_input = []
templates_without_output = []
templates_without_any = []
for template_id, stats in template_stats.items():
status = []
if stats['input_count'] == 0:
status.append("缺少输入字段")
templates_without_input.append(stats)
if stats['output_count'] == 0:
status.append("缺少输出字段")
templates_without_output.append(stats)
if stats['input_count'] == 0 and stats['output_count'] == 0:
templates_without_any.append(stats)
status_str = " | ".join(status) if status else "[OK] 正常"
print(f" {stats['template_name']} (ID: {stats['template_id']})")
print(f" 输入字段: {stats['input_count']} 个 | 输出字段: {stats['output_count']} 个 | {status_str}")
return {
'template_stats': template_stats,
'templates_without_input': templates_without_input,
'templates_without_output': templates_without_output,
'templates_without_any': templates_without_any
}
def check_input_field_relations_detail(conn) -> Dict:
"""详细检查输入字段的关联情况"""
cursor = conn.cursor(pymysql.cursors.DictCursor)
print("\n" + "="*80)
print("2. 详细检查输入字段的关联情况")
print("="*80)
# 获取所有启用的输入字段
cursor.execute("""
SELECT id, name, filed_code
FROM f_polic_field
WHERE tenant_id = %s AND field_type = 1 AND state = 1
ORDER BY name
""", (TENANT_ID,))
input_fields = cursor.fetchall()
# 获取每个输入字段关联的模板
cursor.execute("""
SELECT
f.id AS field_id,
f.name AS field_name,
f.filed_code AS field_code,
fc.id AS template_id,
fc.name AS template_name
FROM f_polic_field f
INNER JOIN f_polic_file_field fff ON f.id = fff.filed_id AND f.tenant_id = fff.tenant_id
INNER JOIN f_polic_file_config fc ON fff.file_id = fc.id AND fff.tenant_id = fc.tenant_id
WHERE f.tenant_id = %s
AND f.field_type = 1
AND f.state = 1
AND fff.state = 1
AND fc.state = 1
ORDER BY f.name, fc.name
""", (TENANT_ID,))
input_field_relations = cursor.fetchall()
# 按字段分组
field_template_map = defaultdict(list)
for rel in input_field_relations:
field_template_map[rel['field_id']].append({
'template_id': rel['template_id'],
'template_name': rel['template_name']
})
print(f"\n共找到 {len(input_fields)} 个启用的输入字段\n")
fields_without_relations = []
fields_with_relations = []
for field in input_fields:
field_id = field['id']
templates = field_template_map.get(field_id, [])
if not templates:
fields_without_relations.append(field)
print(f" [WARN] {field['name']} ({field['filed_code']}) - 未关联任何模板")
else:
fields_with_relations.append({
'field': field,
'templates': templates
})
print(f" [OK] {field['name']} ({field['filed_code']}) - 关联了 {len(templates)} 个模板:")
for template in templates:
print(f" - {template['template_name']} (ID: {template['template_id']})")
return {
'input_fields': input_fields,
'fields_without_relations': fields_without_relations,
'fields_with_relations': fields_with_relations
}
def check_output_field_relations_detail(conn) -> Dict:
"""详细检查输出字段的关联情况"""
cursor = conn.cursor(pymysql.cursors.DictCursor)
print("\n" + "="*80)
print("3. 详细检查输出字段的关联情况")
print("="*80)
# 获取所有启用的输出字段
cursor.execute("""
SELECT id, name, filed_code
FROM f_polic_field
WHERE tenant_id = %s AND field_type = 2 AND state = 1
ORDER BY name
""", (TENANT_ID,))
output_fields = cursor.fetchall()
# 获取每个输出字段关联的模板
cursor.execute("""
SELECT
f.id AS field_id,
f.name AS field_name,
f.filed_code AS field_code,
fc.id AS template_id,
fc.name AS template_name
FROM f_polic_field f
INNER JOIN f_polic_file_field fff ON f.id = fff.filed_id AND f.tenant_id = fff.tenant_id
INNER JOIN f_polic_file_config fc ON fff.file_id = fc.id AND fff.tenant_id = fc.tenant_id
WHERE f.tenant_id = %s
AND f.field_type = 2
AND f.state = 1
AND fff.state = 1
AND fc.state = 1
ORDER BY f.name, fc.name
""", (TENANT_ID,))
output_field_relations = cursor.fetchall()
# 按字段分组
field_template_map = defaultdict(list)
for rel in output_field_relations:
field_template_map[rel['field_id']].append({
'template_id': rel['template_id'],
'template_name': rel['template_name']
})
print(f"\n共找到 {len(output_fields)} 个启用的输出字段\n")
fields_without_relations = []
fields_with_relations = []
for field in output_fields:
field_id = field['id']
templates = field_template_map.get(field_id, [])
if not templates:
fields_without_relations.append(field)
print(f" [WARN] {field['name']} ({field['filed_code']}) - 未关联任何模板")
else:
fields_with_relations.append({
'field': field,
'templates': templates
})
if len(templates) <= 5:
print(f" [OK] {field['name']} ({field['filed_code']}) - 关联了 {len(templates)} 个模板:")
for template in templates:
print(f" - {template['template_name']} (ID: {template['template_id']})")
else:
print(f" [OK] {field['name']} ({field['filed_code']}) - 关联了 {len(templates)} 个模板")
for template in templates[:3]:
print(f" - {template['template_name']} (ID: {template['template_id']})")
print(f" ... 还有 {len(templates) - 3} 个模板")
return {
'output_fields': output_fields,
'fields_without_relations': fields_without_relations,
'fields_with_relations': fields_with_relations
}
def check_invalid_relations(conn) -> Dict:
"""检查无效的关联关系"""
cursor = conn.cursor(pymysql.cursors.DictCursor)
print("\n" + "="*80)
print("4. 检查无效的关联关系")
print("="*80)
# 检查关联到不存在的 file_id
cursor.execute("""
SELECT fff.id, fff.file_id, fff.filed_id, fff.tenant_id
FROM f_polic_file_field fff
LEFT JOIN f_polic_file_config fc ON fff.file_id = fc.id AND fff.tenant_id = fc.tenant_id
WHERE fff.tenant_id = %s AND fc.id IS NULL
""", (TENANT_ID,))
invalid_file_relations = cursor.fetchall()
# 检查关联到不存在的 filed_id
cursor.execute("""
SELECT fff.id, fff.file_id, fff.filed_id, fff.tenant_id
FROM f_polic_file_field fff
LEFT JOIN f_polic_field f ON fff.filed_id = f.id AND fff.tenant_id = f.tenant_id
WHERE fff.tenant_id = %s AND f.id IS NULL
""", (TENANT_ID,))
invalid_field_relations = cursor.fetchall()
print(f"\n关联到不存在的 file_id: {len(invalid_file_relations)}")
if invalid_file_relations:
print(" 详情:")
for rel in invalid_file_relations[:10]:
print(f" - 关联ID: {rel['id']}, file_id: {rel['file_id']}, filed_id: {rel['filed_id']}")
if len(invalid_file_relations) > 10:
print(f" ... 还有 {len(invalid_file_relations) - 10}")
else:
print(" [OK] 没有无效的 file_id 关联")
print(f"\n关联到不存在的 filed_id: {len(invalid_field_relations)}")
if invalid_field_relations:
print(" 详情:")
for rel in invalid_field_relations[:10]:
print(f" - 关联ID: {rel['id']}, file_id: {rel['file_id']}, filed_id: {rel['filed_id']}")
if len(invalid_field_relations) > 10:
print(f" ... 还有 {len(invalid_field_relations) - 10}")
else:
print(" [OK] 没有无效的 filed_id 关联")
return {
'invalid_file_relations': invalid_file_relations,
'invalid_field_relations': invalid_field_relations
}
def get_summary_statistics(conn) -> Dict:
"""获取汇总统计信息"""
cursor = conn.cursor(pymysql.cursors.DictCursor)
print("\n" + "="*80)
print("5. 汇总统计信息")
print("="*80)
# 总关联数
cursor.execute("""
SELECT COUNT(*) as total
FROM f_polic_file_field
WHERE tenant_id = %s AND state = 1
""", (TENANT_ID,))
total_relations = cursor.fetchone()['total']
# 输入字段关联数
cursor.execute("""
SELECT COUNT(*) as total
FROM f_polic_file_field fff
INNER JOIN f_polic_field f ON fff.filed_id = f.id AND fff.tenant_id = f.tenant_id
WHERE fff.tenant_id = %s
AND fff.state = 1
AND f.state = 1
AND f.field_type = 1
""", (TENANT_ID,))
input_relations = cursor.fetchone()['total']
# 输出字段关联数
cursor.execute("""
SELECT COUNT(*) as total
FROM f_polic_file_field fff
INNER JOIN f_polic_field f ON fff.filed_id = f.id AND fff.tenant_id = f.tenant_id
WHERE fff.tenant_id = %s
AND fff.state = 1
AND f.state = 1
AND f.field_type = 2
""", (TENANT_ID,))
output_relations = cursor.fetchone()['total']
# 关联的模板数
cursor.execute("""
SELECT COUNT(DISTINCT file_id) as total
FROM f_polic_file_field
WHERE tenant_id = %s AND state = 1
""", (TENANT_ID,))
related_templates = cursor.fetchone()['total']
# 关联的输入字段数
cursor.execute("""
SELECT COUNT(DISTINCT fff.filed_id) as total
FROM f_polic_file_field fff
INNER JOIN f_polic_field f ON fff.filed_id = f.id AND fff.tenant_id = f.tenant_id
WHERE fff.tenant_id = %s
AND fff.state = 1
AND f.state = 1
AND f.field_type = 1
""", (TENANT_ID,))
related_input_fields = cursor.fetchone()['total']
# 关联的输出字段数
cursor.execute("""
SELECT COUNT(DISTINCT fff.filed_id) as total
FROM f_polic_file_field fff
INNER JOIN f_polic_field f ON fff.filed_id = f.id AND fff.tenant_id = f.tenant_id
WHERE fff.tenant_id = %s
AND fff.state = 1
AND f.state = 1
AND f.field_type = 2
""", (TENANT_ID,))
related_output_fields = cursor.fetchone()['total']
print(f"\n总关联数: {total_relations}")
print(f" 输入字段关联数: {input_relations}")
print(f" 输出字段关联数: {output_relations}")
print(f"\n关联的模板数: {related_templates}")
print(f"关联的输入字段数: {related_input_fields}")
print(f"关联的输出字段数: {related_output_fields}")
return {
'total_relations': total_relations,
'input_relations': input_relations,
'output_relations': output_relations,
'related_templates': related_templates,
'related_input_fields': related_input_fields,
'related_output_fields': related_output_fields
}
def main():
"""主函数"""
print("="*80)
print("全面检查 f_polic_file_field 表的关联关系")
print("="*80)
try:
conn = pymysql.connect(**DB_CONFIG)
print("[OK] 数据库连接成功\n")
except Exception as e:
print(f"[ERROR] 数据库连接失败: {e}")
return
try:
# 1. 检查所有模板的字段关联情况
template_result = check_all_templates_field_relations(conn)
# 2. 详细检查输入字段的关联情况
input_result = check_input_field_relations_detail(conn)
# 3. 详细检查输出字段的关联情况
output_result = check_output_field_relations_detail(conn)
# 4. 检查无效的关联关系
invalid_result = check_invalid_relations(conn)
# 5. 获取汇总统计信息
stats = get_summary_statistics(conn)
# 总结
print("\n" + "="*80)
print("检查总结")
print("="*80)
issues = []
if len(template_result['templates_without_input']) > 0:
issues.append(f"[WARN] {len(template_result['templates_without_input'])} 个模板缺少输入字段关联")
if len(template_result['templates_without_output']) > 0:
issues.append(f"[WARN] {len(template_result['templates_without_output'])} 个模板缺少输出字段关联")
if len(template_result['templates_without_any']) > 0:
issues.append(f"[WARN] {len(template_result['templates_without_any'])} 个模板没有任何字段关联")
if len(input_result['fields_without_relations']) > 0:
issues.append(f"[WARN] {len(input_result['fields_without_relations'])} 个输入字段未关联任何模板")
if len(output_result['fields_without_relations']) > 0:
issues.append(f"[WARN] {len(output_result['fields_without_relations'])} 个输出字段未关联任何模板")
if len(invalid_result['invalid_file_relations']) > 0:
issues.append(f"[ERROR] {len(invalid_result['invalid_file_relations'])} 条无效的 file_id 关联")
if len(invalid_result['invalid_field_relations']) > 0:
issues.append(f"[ERROR] {len(invalid_result['invalid_field_relations'])} 条无效的 filed_id 关联")
if issues:
print("\n发现以下问题:\n")
for issue in issues:
print(f" {issue}")
else:
print("\n[OK] 未发现明显问题")
print("\n" + "="*80)
except Exception as e:
print(f"\n[ERROR] 检查过程中发生错误: {e}")
import traceback
traceback.print_exc()
finally:
conn.close()
print("\n数据库连接已关闭")
if __name__ == '__main__':
main()