| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460 |
- using Newtonsoft.Json.Linq;
- using PTMedicalInsurance.Helper;
- using PTMedicalInsurance.Variables;
- using System;
- using System.Collections.Generic;
- using System.Windows.Forms;
- namespace PTMedicalInsurance.Business
- {
- /// <summary>
- /// 事前事中分析违规日志服务(适配宽表 BS_PreInProcess_ViolationLog)
- /// </summary>
- public class PreAndInProcessAnalysisLogService
- {
- private InvokeHelper invoker = new InvokeHelper();
- /// <summary>
- /// 记录3101/3102交易违规日志(逐条写入宽表)
- /// </summary>
- /// <param name="tradeCode">交易代码(3101,3102)</param>
- /// <param name="tradeName">交易名称</param>
- /// <param name="triggerScene">触发场景</param>
- /// <param name="inputData">输入数据</param>
- /// <param name="outputData">输出数据(含违规结果)</param>
- /// <param name="errMsg">错误信息</param>
- /// <returns>0:成功, -1:失败</returns>
- public int LogPreInProcessAnalysis(string tradeCode, string tradeName, string triggerScene,
- JObject inputData, JObject outputData, out string errMsg)
- {
- errMsg = "";
- try
- {
- JObject joData = inputData["data"] as JObject;
- if (joData == null)
- {
- errMsg = "输入数据格式不正确";
- return -1;
- }
- JArray jaPatientDtos = joData["patient_dtos"] as JArray;
- if (jaPatientDtos == null || jaPatientDtos.Count == 0)
- {
- errMsg = "病人信息为空";
- return -1;
- }
- // 提取交易公共信息
- string taskId = joData["task_id"]?.ToString() ?? "";
- string msgId = inputData["msgid"]?.ToString() ?? "";
- string opterCode = inputData["opter"]?.ToString() ?? Global.user.ID;
- string opterName = inputData["opter_name"]?.ToString() ?? Global.user.name;
- string infTimeStr = inputData["inf_time"]?.ToString() ?? DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
- DateTime infTime = DateTime.TryParse(infTimeStr, out var dtTmp) ? dtTmp : DateTime.Now;
- // 解析违规结果列表(支持对象/数组/judge_result_dtos嵌套)
- List<JObject> violationList = ParseViolationList(outputData);
- if (violationList.Count == 0)
- {
- Global.writeLog($"{tradeCode} 未返回违规结果,无需记录");
- return 0;
- }
- int successCount = 0;
- foreach (JObject joVio in violationList)
- {
- string jrId = joVio["jr_id"]?.ToString() ?? "";
- if (string.IsNullOrEmpty(jrId))
- {
- Global.writeLog($"{tradeCode} 违规结果缺少 jr_id,跳过记录");
- continue;
- }
- JObject joLog = BuildViolationLog(joVio, jaPatientDtos, taskId, tradeCode, tradeName,
- triggerScene, msgId, opterCode, opterName, infTime);
- JObject joParam = new JObject();
- joParam.Add("LogData", joLog);
- joParam.Add("HospitalDr", Global.inf.hospitalDr);
- joParam.Add("InterfaceDr", Global.inf.interfaceDr);
- joParam.Add("UpdateUserID", Global.user.ID);
- string serviceCode = "09010148";
- string inpar = JsonHelper.setIrisInpar(serviceCode, joParam).ToString();
- JObject joRtn = invoker.invokeInsuService(inpar, "记录事前事中违规日志");
- if (JsonHelper.parseIrisRtnValue(joRtn, out string insertErr) == 0)
- {
- successCount++;
- }
- else
- {
- Global.writeLog($"记录违规日志失败(JrID={jrId}): {insertErr}");
- }
- }
- Global.writeLog($"记录{tradeCode}违规日志: 成功{successCount}/{violationList.Count}");
- return successCount > 0 ? 0 : -1;
- }
- catch (Exception ex)
- {
- errMsg = $"记录日志异常: {ex.Message}";
- Global.writeLog($"记录{tradeCode}日志异常: {ex.Message}");
- return -1;
- }
- }
- /// <summary>
- /// 记录3103反馈日志(根据 warn_rslt_id 更新宽表反馈字段)
- /// 说明:3103的 warn_rslt_id 与 3101/3102 的 jr_id 为同一值,均映射到宽表的 JrID 字段
- /// </summary>
- /// <param name="warningType">反馈类型(1:事前,2:事中)</param>
- /// <param name="warnings">反馈数据集合</param>
- /// <param name="errMsg">错误信息</param>
- /// <returns>0:成功, -1:失败</returns>
- public int LogFeedback(string warningType, JArray warnings, out string errMsg)
- {
- errMsg = "";
- try
- {
- if (warnings == null || warnings.Count == 0)
- {
- errMsg = "反馈数据为空";
- return -1;
- }
- int successCount = 0;
- foreach (JObject joWarn in warnings)
- {
- string warnRsltId = joWarn["warn_rslt_id"]?.ToString() ?? "";
- string dspoWay = joWarn["dspo_way"]?.ToString() ?? "";
- string dspoWayRea = joWarn["dspo_way_rea"]?.ToString() ?? "";
- if (string.IsNullOrEmpty(warnRsltId))
- {
- continue;
- }
- JObject joLog = new JObject();
- joLog.Add("JrID", warnRsltId); // 对应宽表 JrID
- joLog.Add("DspoWay", dspoWay);
- joLog.Add("DspoWayRea", dspoWayRea);
- joLog.Add("WarnType", warningType);
- joLog.Add("FeedbackDate", DateTime.Now.ToString("yyyy-MM-dd"));
- joLog.Add("FeedbackTime", DateTime.Now.ToString("HH:mm:ss"));
- joLog.Add("OpterCode", Global.user.ID);
- joLog.Add("OpterName", Global.user.name);
- JObject joParam = new JObject();
- joParam.Add("LogData", joLog);
- joParam.Add("HospitalDr", Global.inf.hospitalDr);
- joParam.Add("InterfaceDr", Global.inf.interfaceDr);
- joParam.Add("UpdateUserID", Global.user.ID);
- string serviceCode = "09010148";
- string inpar = JsonHelper.setIrisInpar(serviceCode, joParam).ToString();
- JObject joRtn = invoker.invokeInsuService(inpar, "更新事前事中反馈日志");
- if (JsonHelper.parseIrisRtnValue(joRtn, out string updateErr) == 0)
- {
- successCount++;
- }
- else
- {
- Global.writeLog($"更新反馈日志失败(WarnRsltID={warnRsltId}): {updateErr}");
- }
- }
- Global.writeLog($"记录3103反馈日志: 成功{successCount}/{warnings.Count}");
- return successCount > 0 ? 0 : -1;
- }
- catch (Exception ex)
- {
- errMsg = $"记录反馈日志异常: {ex.Message}";
- Global.writeLog($"记录3103反馈日志异常: {ex.Message}");
- return -1;
- }
- }
- /// <summary>
- /// 查询违规日志(支持操作员、病人姓名、项目名称过滤)
- /// </summary>
- public System.Data.DataTable QueryLogs(string startDate, string endDate,
- string operatorName, string patientName, string itemName, out string errMsg)
- {
- errMsg = "";
- try
- {
- string sqlStr = $"SELECT * FROM SQLUser.BS_PreInProcess_ViolationLog where 1=1 and Interface_Dr = {Global.inf.interfaceDr}";
-
- sqlStr += $" and InfDate>='{startDate}' and InfDate<='{endDate}'";
- if (!string.IsNullOrEmpty(operatorName))
- {
- sqlStr += $" and OpterName = {operatorName}";
- }
- if (!string.IsNullOrEmpty(patientName))
- {
- sqlStr += $" and PatnName = {patientName}";
- }
- if (!string.IsNullOrEmpty(itemName))
- {
- sqlStr += $" and ItemName = {itemName}";
- }
- MIIrisServices mis= new MIIrisServices();
- JObject joRtn = mis.DynamicQuery(sqlStr, "查询");
- if (JsonHelper.parseIrisRtnValue(joRtn, out errMsg) != 0)
- {
- return null;
- }
- return joRtn["result"]?["data"]?.ToObject<System.Data.DataTable>();
- }
- catch (Exception ex)
- {
- errMsg = $"查询日志异常: {ex.Message}";
- return null;
- }
- }
- /// <summary>
- /// 按日期范围查询违规日志
- /// </summary>
- public System.Data.DataTable QueryLogsByDate(string startDate, string endDate, out string errMsg)
- {
- return QueryLogs(startDate, endDate, "", "", "", out errMsg);
- }
- #region 私有辅助方法
- /// <summary>
- /// 从输出数据中解析违规结果列表
- /// </summary>
- private List<JObject> ParseViolationList(JObject outputData)
- {
- List<JObject> list = new List<JObject>();
- if (outputData == null) return list;
- JToken jtResult = outputData["output"]["result"];
- if (jtResult is JArray jaResult)
- {
- foreach (JToken jt in jaResult)
- {
- if (jt is JObject jo) list.Add(jo);
- }
- }
- else if (jtResult is JObject joResult)
- {
- JArray jaJudgeResults = joResult["judge_result_dtos"] as JArray;
- if (jaJudgeResults != null && jaJudgeResults.Count > 0)
- {
- foreach (JToken jt in jaJudgeResults)
- {
- if (jt is JObject jo) list.Add(jo);
- }
- }
- else
- {
- list.Add(joResult);
- }
- }
- return list;
- }
- /// <summary>
- /// 构建单条违规宽表记录
- /// </summary>
- private JObject BuildViolationLog(JObject joVio, JArray jaPatientDtos, string taskId,
- string tradeCode, string tradeName, string triggerScene, string msgId,
- string opterCode, string opterName, DateTime infTime)
- {
- JObject joLog = new JObject();
- // 交易头部
- joLog.Add("TaskID", taskId);
- joLog.Add("TradeCode", tradeCode);
- joLog.Add("TriggerScene", triggerScene);
- joLog.Add("MsgID", msgId);
- joLog.Add("OpterCode", opterCode);
- joLog.Add("OpterName", opterName);
- joLog.Add("InfDate", infTime.ToString("yyyy-MM-dd"));
- joLog.Add("InfTime", infTime.ToString("HH:mm:ss"));
- // 违规信息
- string jrId = joVio["jr_id"]?.ToString() ?? "";
- string patnId = joVio["patn_id"]?.ToString() ?? "";
- string mdtrtId = joVio["mdtrt_id"]?.ToString() ?? "";
- joLog.Add("WarnType", joVio["warn_type"]?.ToString() ?? "");
- joLog.Add("JrID", jrId);
- joLog.Add("RuleID", joVio["rule_id"]?.ToString() ?? "");
- joLog.Add("RuleName", joVio["rule_name"]?.ToString() ?? "");
- joLog.Add("VolaCont", joVio["vola_cont"]?.ToString() ?? "");
- joLog.Add("VolaAmt", ParseDecimal(joVio["vola_amt"]));
- joLog.Add("SevDeg", joVio["sev_deg"]?.ToString() ?? "");
- joLog.Add("VolaBhvrType", joVio["vola_bhvr_type"]?.ToString() ?? "");
- joLog.Add("PatnID", patnId);
- joLog.Add("MdtrtID", mdtrtId);
- // 匹配患者与就诊信息
- JObject joPatient = FindPatientById(jaPatientDtos, patnId);
- if (joPatient != null)
- {
- joLog.Add("PatnName", joPatient["patn_name"]?.ToString() ?? "");
- joLog.Add("Gend", joPatient["gend"]?.ToString() ?? "");
- joLog.Add("Brdy", joPatient["brdy"]?.ToString() ?? "");
- JArray jaEncounters = joPatient["fsi_encounter_dtos"] as JArray;
- JObject joEncounter = FindEncounterById(jaEncounters, mdtrtId);
- if (joEncounter != null)
- {
- joLog.Add("DeptName", joEncounter["adm_dept_name"]?.ToString() ?? "");
- string medType = joEncounter["med_type"]?.ToString() ?? "";
- joLog.Add("MedType", medType);
- joLog.Add("MedTypeName", MedTypeToName(medType));
- // 项目信息:优先从违规明细匹配,其次取就诊的第一个医嘱
- FillItemInfo(joLog, joVio, joEncounter);
- }
- }
- // 确保项目字段有默认值
- EnsureDefault(joLog, "ItemCode", "");
- EnsureDefault(joLog, "ItemName", "");
- EnsureDefault(joLog, "Cnt", 0);
- EnsureDefault(joLog, "Pric", 0);
- EnsureDefault(joLog, "Sumamt", 0);
- return joLog;
- }
- /// <summary>
- /// 填充项目信息(违规明细 -> 医嘱匹配 -> 默认值)
- /// </summary>
- private void FillItemInfo(JObject joLog, JObject joVio, JObject joEncounter)
- {
- JArray jaOrders = joEncounter["fsi_order_dtos"] as JArray;
- JArray jaDetails = joVio["judge_result_detail_dtos"] as JArray;
- JObject joOrder = null;
- if (jaDetails != null && jaDetails.Count > 0)
- {
- JObject joDetail = jaDetails[0] as JObject;
- string detailRxId = joDetail["rx_id"]?.ToString() ?? "";
- if (!string.IsNullOrEmpty(detailRxId) && jaOrders != null)
- {
- joOrder = FindOrderByRxId(jaOrders, detailRxId);
- }
- // 若未匹配到order,先取明细中的项目信息
- if (joOrder == null)
- {
- joLog.Add("ItemCode", joDetail["hilist_code"]?.ToString() ?? joDetail["item_code"]?.ToString() ?? "");
- joLog.Add("ItemName", joDetail["hilist_name"]?.ToString() ?? joDetail["item_name"]?.ToString() ?? "");
- joLog.Add("Cnt", ParseDecimal(joDetail["cnt"]));
- joLog.Add("Pric", ParseDecimal(joDetail["pric"]));
- joLog.Add("Sumamt", ParseDecimal(joDetail["sumamt"]));
- }
- }
- // 从医嘱取项目信息
- if (joOrder == null && jaOrders != null && jaOrders.Count > 0)
- {
- joOrder = jaOrders[0] as JObject;
- }
- if (joOrder != null && !joLog.ContainsKey("ItemName"))
- {
- joLog.Add("ItemCode", joOrder["hilist_code"]?.ToString() ?? joOrder["hosplist_code"]?.ToString() ?? "");
- joLog.Add("ItemName", joOrder["hilist_name"]?.ToString() ?? joOrder["hosplist_name"]?.ToString() ?? "");
- joLog.Add("Cnt", ParseDecimal(joOrder["cnt"]));
- joLog.Add("Pric", ParseDecimal(joOrder["pric"]));
- joLog.Add("Sumamt", ParseDecimal(joOrder["sumamt"]));
- }
- }
- /// <summary>
- /// 根据参保人ID查找患者对象
- /// </summary>
- private JObject FindPatientById(JArray jaPatientDtos, string patnId)
- {
- if (jaPatientDtos == null || string.IsNullOrEmpty(patnId)) return null;
- foreach (JToken jt in jaPatientDtos)
- {
- if (jt is JObject jo && jo["patn_id"]?.ToString() == patnId)
- return jo;
- }
- // 若ID匹配不到,返回第一个作为兜底
- return jaPatientDtos.Count > 0 ? jaPatientDtos[0] as JObject : null;
- }
- /// <summary>
- /// 根据就诊ID查找就诊对象
- /// </summary>
- private JObject FindEncounterById(JArray jaEncounters, string mdtrtId)
- {
- if (jaEncounters == null || string.IsNullOrEmpty(mdtrtId)) return null;
- foreach (JToken jt in jaEncounters)
- {
- if (jt is JObject jo && jo["mdtrt_id"]?.ToString() == mdtrtId)
- return jo;
- }
- return jaEncounters.Count > 0 ? jaEncounters[0] as JObject : null;
- }
- /// <summary>
- /// 根据处方ID查找医嘱对象
- /// </summary>
- private JObject FindOrderByRxId(JArray jaOrders, string rxId)
- {
- if (jaOrders == null || string.IsNullOrEmpty(rxId)) return null;
- foreach (JToken jt in jaOrders)
- {
- if (jt is JObject jo && jo["rx_id"]?.ToString() == rxId)
- return jo;
- }
- return null;
- }
- /// <summary>
- /// 医疗类别编码转中文名称
- /// </summary>
- private string MedTypeToName(string medType)
- {
- switch (medType)
- {
- case "11": return "普通门诊";
- case "13": return "门诊慢特病";
- case "21": return "普通住院";
- case "22": return "住院分娩";
- case "24": return "急诊留观转住院";
- case "25": return "日间手术";
- case "51": return "生育门诊";
- case "52": return "生育住院";
- default: return medType;
- }
- }
- /// <summary>
- /// 安全解析数值
- /// </summary>
- private decimal ParseDecimal(JToken jtValue)
- {
- if (jtValue == null) return 0;
- if (decimal.TryParse(jtValue.ToString(), out decimal result))
- return result;
- return 0;
- }
- /// <summary>
- /// 确保字段存在默认值
- /// </summary>
- private void EnsureDefault(JObject jo, string key, object defaultValue)
- {
- if (!jo.ContainsKey(key))
- jo.Add(key, JToken.FromObject(defaultValue));
- }
- #endregion
- }
- }
|