import json import os import sys from datetime import date, timedelta from decimal import Decimal from io import BytesIO from itertools import groupby import requests from PIL import ImageFont, ImageDraw, Image from sqlalchemy import update from db import MysqlSession from db.mysql import ViewErrorReview, ZxPhhd, ZxPhrec, ZxIeResult, ZxIeSettlement, ZxIeDischarge, ZxIeCost from ucloud import ufile from util import image_util def main(pk_phhd=None): session = MysqlSession() error_query = (session.query(ZxPhhd.pk_phhd, ZxPhhd.cXm, ViewErrorReview.pk_yljg, ViewErrorReview.pk_yljg_ocr, ViewErrorReview.pk_ylks, ViewErrorReview.pk_ylks_ocr, ViewErrorReview.cdoctor, ViewErrorReview.cdoctor_ocr, ViewErrorReview.czyh, ViewErrorReview.czyh_ocr, ViewErrorReview.dzyrq, ViewErrorReview.dzyrq_ocr, ViewErrorReview.dcyrq, ViewErrorReview.dcyrq_ocr, ViewErrorReview.input_cxm, ViewErrorReview.input_cxm_ocr, ViewErrorReview.ffsylfy, ViewErrorReview.ffsylfy_ocr, ViewErrorReview.fgrzfje1, ViewErrorReview.fgrzfje1_ocr, ViewErrorReview.fgezfje2, ViewErrorReview.fgezfje2_ocr, ViewErrorReview.fgrzfje, ViewErrorReview.fgrzfje_ocr, ViewErrorReview.yb_type, ViewErrorReview.yb_type_ocr, ViewErrorReview.cjsd_id, ViewErrorReview.cjsd_id_ocr, ViewErrorReview.fage, ViewErrorReview.fage_ocr, ZxPhhd.problem_note) .join(ZxPhhd, ViewErrorReview.pk_phhd == ZxPhhd.pk_phhd, isouter=True)) if pk_phhd: error_query = error_query.filter(ZxPhhd.pk_phhd == pk_phhd) else: today = date.today() error_query = (error_query.filter(ZxPhhd.problem_note.is_(None)) .filter(ViewErrorReview.creationtime >= today) .filter(ViewErrorReview.creationtime < today + timedelta(days=1)) .order_by(ViewErrorReview.creationtime.desc())) error_review = error_query.limit(1).one_or_none() if error_review is None: print("没有需要检查的记录") sys.exit() pk_phhd = error_review.pk_phhd # 文件路径 directory = f"./review_error_check/{pk_phhd}" if not os.path.exists(directory): os.makedirs(directory) json_result = { "pk_phhd": pk_phhd, "cXm": error_review.cXm } settlement_query = session.query(ZxIeSettlement.pk_ie_settlement) discharge_query = session.query(ZxIeDischarge.pk_ie_discharge) cost_query = session.query(ZxIeCost.pk_ie_cost) if error_review.pk_yljg != error_review.pk_yljg_ocr: json_result["医院pk_yljg"] = error_review.pk_yljg json_result["pk_yljg_ocr"] = error_review.pk_yljg_ocr discharge_query = discharge_query.add_columns(ZxIeDischarge.hospital, ZxIeDischarge.pk_yljg) if error_review.pk_ylks != error_review.pk_ylks_ocr: json_result["科室pk_ylks"] = error_review.pk_ylks json_result["pk_ylks_ocr"] = error_review.pk_ylks_ocr discharge_query = discharge_query.add_columns(ZxIeDischarge.department, ZxIeDischarge.pk_ylks) if error_review.cdoctor != error_review.cdoctor_ocr: json_result["医生cdoctor"] = error_review.cdoctor json_result["cdoctor_ocr"] = error_review.cdoctor_ocr discharge_query = discharge_query.add_column(ZxIeDischarge.doctor) if error_review.czyh != error_review.czyh_ocr: json_result["住院号czyh"] = error_review.czyh json_result["czyh_ocr"] = error_review.czyh_ocr settlement_query = settlement_query.add_column(ZxIeSettlement.admission_id) discharge_query = discharge_query.add_column(ZxIeDischarge.admission_id) if error_review.dzyrq != error_review.dzyrq_ocr: json_result["入院日期dzyrq"] = error_review.dzyrq json_result["dzyrq_ocr"] = error_review.dzyrq_ocr settlement_query = settlement_query.add_columns(ZxIeSettlement.admission_date_str, ZxIeSettlement.admission_date) discharge_query = discharge_query.add_columns(ZxIeDischarge.admission_date_str, ZxIeDischarge.admission_date) cost_query = cost_query.add_columns(ZxIeCost.admission_date_str, ZxIeCost.admission_date) if error_review.dcyrq != error_review.dcyrq_ocr: json_result["出院日期dcyrq"] = error_review.dcyrq json_result["dcyrq_ocr"] = error_review.dcyrq_ocr settlement_query = settlement_query.add_columns(ZxIeSettlement.discharge_date_str, ZxIeSettlement.discharge_date) discharge_query = discharge_query.add_columns(ZxIeDischarge.discharge_date_str, ZxIeDischarge.discharge_date) cost_query = cost_query.add_columns(ZxIeCost.discharge_date_str, ZxIeCost.discharge_date) if error_review.input_cxm != error_review.input_cxm_ocr: json_result["姓名input_cxm"] = error_review.input_cxm json_result["input_cxm_ocr"] = error_review.input_cxm_ocr settlement_query = settlement_query.add_column(ZxIeSettlement.name) discharge_query = discharge_query.add_column(ZxIeDischarge.name) cost_query = cost_query.add_column(ZxIeCost.name) if error_review.ffsylfy != error_review.ffsylfy_ocr: json_result["费用总额ffsylfy"] = error_review.ffsylfy json_result["ffsylfy_ocr"] = error_review.ffsylfy_ocr settlement_query = settlement_query.add_columns(ZxIeSettlement.medical_expenses_str, ZxIeSettlement.medical_expenses) cost_query = cost_query.add_columns(ZxIeCost.medical_expenses_str, ZxIeCost.medical_expenses) if error_review.fgrzfje1 != error_review.fgrzfje1_ocr: json_result["个人现金支付fgrzfje1"] = error_review.fgrzfje1 json_result["fgrzfje1_ocr"] = error_review.fgrzfje1_ocr settlement_query = settlement_query.add_columns(ZxIeSettlement.personal_cash_payment_str, ZxIeSettlement.personal_cash_payment) if error_review.fgezfje2 != error_review.fgezfje2_ocr: json_result["个人账户支付fgezfje2"] = error_review.fgezfje2 json_result["fgezfje2_ocr"] = error_review.fgezfje2_ocr settlement_query = settlement_query.add_columns(ZxIeSettlement.personal_account_payment_str, ZxIeSettlement.personal_account_payment) if error_review.fgrzfje != error_review.fgrzfje_ocr: json_result["个人自费fgrzfje"] = error_review.fgrzfje json_result["fgrzfje_ocr"] = error_review.fgrzfje_ocr settlement_query = settlement_query.add_columns(ZxIeSettlement.personal_funded_amount_str, ZxIeSettlement.personal_funded_amount) if error_review.yb_type != error_review.yb_type_ocr: json_result["医保类型yb_type"] = error_review.yb_type json_result["yb_type_ocr"] = error_review.yb_type_ocr settlement_query = settlement_query.add_columns(ZxIeSettlement.medical_insurance_type_str, ZxIeSettlement.medical_insurance_type) if error_review.cjsd_id != error_review.cjsd_id_ocr: json_result["结算单号cjsd_id"] = error_review.cjsd_id json_result["cjsd_id_ocr"] = error_review.cjsd_id_ocr settlement_query = settlement_query.add_column(ZxIeSettlement.settlement_id) if error_review.fage != error_review.fage_ocr: json_result["年龄fage"] = error_review.fage json_result["fage_ocr"] = error_review.fage_ocr discharge_query = discharge_query.add_column(ZxIeDischarge.age) settlement = settlement_query.filter(ZxIeSettlement.pk_phhd == pk_phhd).one_or_none() if settlement is not None: json_result["settlement"] = settlement._asdict() discharge = discharge_query.filter(ZxIeDischarge.pk_phhd == pk_phhd).one_or_none() if discharge is not None: json_result["discharge"] = discharge._asdict() cost = cost_query.filter(ZxIeCost.pk_phhd == pk_phhd).one_or_none() if cost is not None: json_result["cost"] = cost._asdict() phrecs = session.query(ZxPhrec.pk_phrec, ZxPhrec.pk_phhd, ZxPhrec.cRectype, ZxPhrec.cfjaddress).filter( ZxPhrec.pk_phhd == pk_phhd).all() for phrec in phrecs: img_name = phrec.cfjaddress img_path = ufile.get_private_url(img_name) response = requests.get(img_path) image = Image.open(BytesIO(response.content)).convert("RGB") font_size = image.width * image.height / 200000 font = ImageFont.truetype("./font/simfang.ttf", size=font_size) ie_result = session.query(ZxIeResult.id, ZxIeResult.content, ZxIeResult.rotation_angle, ZxIeResult.x_offset, ZxIeResult.y_offset).filter(ZxIeResult.pk_phrec == phrec.pk_phrec).all() if not ie_result: no_ie_directory = f"{directory}/0" if not os.path.exists(no_ie_directory): os.makedirs(no_ie_directory) image.save(f"{no_ie_directory}/{img_name}") for _, group_results in groupby(ie_result, key=lambda x: x.id): draw = ImageDraw.Draw(image) for ocr_item in group_results: result = json.loads(ocr_item.content) rotation_angle = ocr_item.rotation_angle x_offset = ocr_item.x_offset y_offset = ocr_item.y_offset for key in result: for value in result[key]: box = value["bbox"][0] if rotation_angle: box = image_util.invert_rotate_rectangle(box, (image.width / 2, image.height / 2), rotation_angle) if x_offset: box[0] += x_offset box[2] += x_offset if y_offset: box[1] += y_offset box[3] += y_offset draw.rectangle(box, outline="red", width=2) # 绘制矩形 draw.text((box[0], box[1] - font_size), key, fill="blue", font=font) # 在矩形上方绘制文本 draw.text((box[0], box[3]), value["text"], fill="blue", font=font) # 在矩形下方绘制文本 ie_directory = f"{directory}/{ocr_item.id}" os.makedirs(ie_directory, exist_ok=True) image.save(f"{ie_directory}/{img_name}") session.close() # 自定义JSON处理器 def default(obj): if isinstance(obj, Decimal): return float(obj) if isinstance(obj, date): return obj.strftime("%Y-%m-%d") with open(f"{directory}/result.json", "w", encoding="utf-8") as json_file: json.dump(json_result, json_file, indent=4, ensure_ascii=False, default=default) return pk_phhd if __name__ == '__main__': pk_phhd = main() while True: check_finish = input(f"{pk_phhd}是否完成(是/否):") if check_finish == "是": """ 错误描述的写法: 1. 查看result.json,以含中文的key中的中文为现在的key 2. 为方便输入,key之后跟中文冒号 3. 冒号之后写错误原因,原因最好是固定的几种写法 4. 可以在原因后跟中文括号,并在括号中进行补充说明 5. 写完错误原因以中文分号结尾,最后一个可以不加分号 举例: 错误描述:医院:未知错误;科室:还是未知错误(补充说明) """ error_descript = input("错误描述:") break elif check_finish == "否": sys.exit() else: print("无效输入!请输入“是”或者“否”") session = MysqlSession() update_error = update(ZxPhhd).where(ZxPhhd.pk_phhd == pk_phhd).values(problem_note=error_descript) session.execute(update_error) session.commit() session.close() print(f"【{pk_phhd}】错误分析已完成。错误描述:{error_descript}")