test_document_processing.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. from app.services.document_processing import (
  2. _build_structured_summary,
  3. _compact_analysis_summary,
  4. extract_dust_dispersion_free_silica_plan,
  5. extract_safety_monitoring_ledger,
  6. normalize_extraction_result,
  7. resolve_effective_parse_mode,
  8. )
  9. def test_compact_analysis_summary_keeps_numbered_results() -> None:
  10. summary = (
  11. "1. 有效期:正常;2. 双机能力:一致;3. 单位资质:需核验;"
  12. "4. 授权签字人:合规;5. 检验仪器:有效;6. 特性曲线:完整;"
  13. "7. 证书证号:齐全;8. 风量风压:差异较小。"
  14. )
  15. compacted = _compact_analysis_summary(summary)
  16. assert "1. 有效期:正常" in compacted
  17. assert "8. 风量风压:差异较小" in compacted
  18. assert len(compacted.splitlines()) == 8
  19. def test_legacy_word_file_upgrades_to_precision_mode() -> None:
  20. assert resolve_effective_parse_mode("lightweight", ".doc") == "precision"
  21. assert resolve_effective_parse_mode("lightweight", ".docx") == "lightweight"
  22. def test_compact_summary_does_not_split_decimal_values() -> None:
  23. summary = "1. 主要路线:883.2Pa,误差2.58%;2. 次要路线:866.42Pa,误差0.63%。"
  24. compacted = _compact_analysis_summary(summary)
  25. assert "883.2Pa" in compacted
  26. assert "866.42Pa" in compacted
  27. def test_resistance_summary_uses_structured_results() -> None:
  28. summary = _build_structured_summary(
  29. "mine_ventilation_resistance_report",
  30. {
  31. "main_route_measured_resistance": "883.2 Pa",
  32. "main_route_relative_error": "2.58",
  33. "secondary_route_measured_resistance": "866.42 Pa",
  34. "secondary_route_relative_error": "0.63",
  35. "equivalent_orifice": "6.77",
  36. "ventilation_difficulty": "容易",
  37. "effective_airflow_rate": "94.6",
  38. "effective_airflow_rate_pass": "合格",
  39. "overall_assessment": "满足要求",
  40. },
  41. )
  42. assert "主要路线:883.2 Pa" in summary
  43. assert "次要路线:866.42 Pa" in summary
  44. def test_effective_airflow_rate_above_85_is_qualified() -> None:
  45. summary = _build_structured_summary(
  46. "airflow_measurement_decadal_report",
  47. {
  48. "measurement_date": "2025-05-16",
  49. "mine_name": "上湾煤矿",
  50. "effective_airflow_rate": "93.93",
  51. },
  52. )
  53. assert "有效风量率 93.93%,合格" in summary
  54. def test_safety_monitoring_ledger_deterministic_parser(tmp_path) -> None:
  55. from openpyxl import Workbook
  56. path = tmp_path / "安全监控系统台账202507.xlsx"
  57. workbook = Workbook()
  58. total = workbook.active
  59. total.title = "总台账"
  60. total.append(["编码", "安装地点", "设备名称", "安装位置", "单位", "报警值", "断电值", "复电值", "断电范围"])
  61. total.append([1, "主井变电所", "综合分站", "主井变电所", "---", "---", "---", "---", "---"])
  62. total.append([1, "主井变电所", "甲烷", "原煤仓", "%", ">=1.5%", ">=1.5%", "<1.5%", "原煤仓电源"])
  63. cover = workbook.create_sheet("台账封面")
  64. cover["A1"] = "上湾矿安全监测系统设备台账"
  65. cover["A2"] = "上湾煤矿通风队"
  66. workbook.save(path)
  67. workbook.close()
  68. result = extract_safety_monitoring_ledger(str(path))
  69. assert result is not None
  70. fields = {item["field_key"]: item["normalized_value"] for item in result["fields"]}
  71. assert fields["substation_count"] == 1
  72. assert fields["sensor_count"] == 1
  73. assert fields["gas_sensor_count"] == 1
  74. def test_dust_dispersion_free_silica_plan_parser(tmp_path) -> None:
  75. from openpyxl import Workbook
  76. path = tmp_path / "粉尘分散度游离二氧化硅监测计划.xlsx"
  77. workbook = Workbook()
  78. sheet = workbook.active
  79. sheet.title = "粉尘检测计划"
  80. sheet.append(["附件:2025年采掘作业场所粉尘分散度、游离二氧化硅含量监测计划表"])
  81. sheet.append(
  82. [
  83. "序号",
  84. "矿井名称",
  85. "现场采样时间",
  86. "检测地点",
  87. "检测项目",
  88. "频次/周期",
  89. "联系人及联系方式",
  90. "",
  91. "备注",
  92. "计划检测时间",
  93. "实际检测日期",
  94. ]
  95. )
  96. sheet.append(
  97. [
  98. 1,
  99. "上湾煤矿",
  100. "1-12月",
  101. "12煤、22煤采掘工作面",
  102. "总粉尘\n粉尘分散度\n游离二氧化硅",
  103. "1次/半年",
  104. "李玉福",
  105. "18047378769",
  106. "每个煤层至少选择一个采掘工作面",
  107. "",
  108. "",
  109. ]
  110. )
  111. sheet.append(["", "", "", "", "", "", "现场检测联系人", "王杰\n18047382145"])
  112. workbook.save(path)
  113. workbook.close()
  114. result = extract_dust_dispersion_free_silica_plan(str(path))
  115. assert result is not None
  116. fields = {item["field_key"]: item["normalized_value"] for item in result["fields"]}
  117. assert fields["monitoring_year"] == "2025"
  118. assert fields["mine_count"] == 1
  119. assert fields["plan_record_count"] == 1
  120. assert fields["monitoring_items"] == ["总粉尘", "粉尘分散度", "游离二氧化硅"]
  121. assert fields["onsite_contacts"][0]["contact_name"] == "王杰"
  122. assert fields["onsite_contacts"][0]["phone"] == "18047382145"
  123. def test_normalized_field_uses_template_chinese_name() -> None:
  124. result = normalize_extraction_result(
  125. {
  126. "fields": [
  127. {
  128. "field_key": "mine_count",
  129. "field_name": "mine_count",
  130. "field_value": 13,
  131. "normalized_value": 13,
  132. }
  133. ]
  134. },
  135. [
  136. {
  137. "key": "mine_count",
  138. "name": "覆盖矿井数量",
  139. "type": "number",
  140. "group_key": "plan_summary",
  141. "group_name": "监测计划汇总",
  142. "group_order": 2,
  143. "field_order": 0,
  144. }
  145. ],
  146. model_status="test",
  147. parsed_markdown="",
  148. template_code="dust_dispersion_free_silica_monitoring_ledger",
  149. )
  150. assert result["fields"][0]["field_name"] == "覆盖矿井数量"