VerifyCaseFrontSheet.java 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. package thyyxxk.webserver.service.inpatient.casefrontsheet;
  2. import lombok.extern.slf4j.Slf4j;
  3. import thyyxxk.webserver.constants.Capacity;
  4. import thyyxxk.webserver.entity.casefrontsheet.CaseFrontsheetDisdiag;
  5. import thyyxxk.webserver.entity.casefrontsheet.CaseFrontsheetMain;
  6. import thyyxxk.webserver.entity.casefrontsheet.CaseFrontsheetSurgery;
  7. import thyyxxk.webserver.entity.casefrontsheet.StandardAddressMember;
  8. import thyyxxk.webserver.entity.dictionary.CodeName;
  9. import thyyxxk.webserver.utils.*;
  10. import java.util.*;
  11. import java.util.regex.Matcher;
  12. import java.util.regex.Pattern;
  13. /**
  14. * @author dj
  15. */
  16. @Slf4j
  17. public class VerifyCaseFrontSheet {
  18. private static VerifyCaseFrontSheet INSTANCE;
  19. private VerifyCaseFrontSheet() { }
  20. public static VerifyCaseFrontSheet getInstance() {
  21. if (null == INSTANCE) {
  22. INSTANCE = new VerifyCaseFrontSheet();
  23. }
  24. return INSTANCE;
  25. }
  26. public List<CodeName> saveVerify(CaseFrontsheetMain sheet) {
  27. List<CodeName> array = new ArrayList<>();
  28. // if (null != sheet.getLivePlace()) {
  29. // try {
  30. // byte[] livePlaceBytes = sheet.getLivePlace().getBytes("GBK");
  31. // if (livePlaceBytes.length > 250) {
  32. // array.add(new CodeName("livePlace", "患者现住址不能超过32个字节,当前字节数为" +
  33. // livePlaceBytes.length + "(1汉字=2字节,1字母或数字=1字节)!"));
  34. // }
  35. // } catch (Exception e) {
  36. // log.error("分析患者现住址长度出现异常", e);
  37. // }
  38. // }
  39. // 移除工作单位地址长度限制
  40. // if (null != sheet.getUnitPlace() && sheet.getUnitPlace().length() > 16) {
  41. // array.add(new CodeName("unitPlace", "患者单位地址不能超过16个汉字!"));
  42. // }
  43. // 移除联系人地址字数限制验证
  44. // if (null != sheet.getContactAddrName() && sheet.getContactAddrName().length() > 16) {
  45. // array.add(new CodeName("contactAddrName", "患者联系人地址不能超过16个汉字!"));
  46. // }
  47. if (DateUtil.daysBetween(sheet.getQualityControlDate(), sheet.getDismissDate()) > 7) {
  48. array.add(new CodeName("qualityControlDate", "质控日期不能大于出院7天!"));
  49. }
  50. return connectedVerify(array, sheet);
  51. }
  52. public List<CodeName> adviseVerification(String socialNo, Date birth, String mainDisdiagCode , Integer age , String marriage) {
  53. List<CodeName> array = new ArrayList<>();
  54. if (StringUtil.invalidValue(socialNo)) {
  55. array.add(new CodeName("socialNo","请补全患者身份证!"));
  56. }
  57. if (!IdCardUtil.isValidatedIdCard(socialNo)) {
  58. array.add(new CodeName("socialNo","患者身份证不合法!"));
  59. }
  60. if (StringUtil.notBlank(socialNo) && socialNo.length() == 18) {
  61. if (null == birth) {
  62. array.add(new CodeName("birthDate","患者出生日期与身份证不符!"));
  63. } else {
  64. String b = DateUtil.format(birth, "yyyyMMdd");
  65. if (!socialNo.substring(6,14).equals(b)) {
  66. array.add(new CodeName("birthDate","患者出生日期与身份证不符!"));
  67. }
  68. }
  69. }
  70. if (null != age && age < 20 && !marriage.equals("1")) {
  71. array.add(new CodeName("marriage", "患者年龄小于20周岁,婚姻状况须填未婚。"));
  72. }
  73. validateMainDiagnose(mainDisdiagCode, array);
  74. return array;
  75. }
  76. public List<CodeName> printVerify(CaseFrontsheetMain info) {
  77. List<CodeName> array = new ArrayList<>();
  78. if (StringUtil.isBlank(info.getPayMethod())) {
  79. array.add(new CodeName("payMethod", "医疗付费方式不能为空!"));
  80. }
  81. if (StringUtil.invalidValue(info.getName())) {
  82. array.add(new CodeName("name", "患者姓名不能为空!"));
  83. }
  84. if (null == info.getBirthDate()) {
  85. array.add(new CodeName("birthDate", "患者出生日期不能为空!"));
  86. }
  87. if (null == info.getAge()) {
  88. array.add(new CodeName("age","患者年龄不能为空!"));
  89. }
  90. if (StringUtil.invalidValue(info.getCountry())) {
  91. array.add(new CodeName("country","患者国籍不能为空!"));
  92. }
  93. if (StringUtil.invalidBirthPlace(info.getBirthPlace()) || StringUtil.invalidValue(info.getBirthPlaceName())) {
  94. array.add(new CodeName("birthPlaceName","患者出生地不能为空!"));
  95. }
  96. if (StringUtil.invalidValue(info.getNativePlace())) {
  97. array.add(new CodeName("nativePlaceName","患者籍贯不能为空!"));
  98. }
  99. if (StringUtil.invalidValue(info.getNation())) {
  100. array.add(new CodeName("nation","患者民族不能为空!"));
  101. }
  102. if (StringUtil.invalidValue(info.getOccupation())) {
  103. array.add(new CodeName("occupation","患者职业不能为空!"));
  104. }
  105. if (StringUtil.invalidValue(info.getMarriage())) {
  106. array.add(new CodeName("marriage","患者婚姻状况不能为空!"));
  107. }
  108. if (StringUtil.invalidValue(info.getLivePlace())) {
  109. array.add(new CodeName("livePlace","患者现住址不能为空!"));
  110. }
  111. // if (info.isDoctorPrint() && null != info.getAddressMember() && StringUtil.notBlank(info.getLivePlace())) {
  112. // String liveAddress = info.getLivePlace();
  113. // StandardAddressMember member = info.getAddressMember();
  114. // if (liveAddress.contains(member.getProvinceName()) || liveAddress.contains(member.getCityName()) ||
  115. // liveAddress.contains(member.getDistrictName())) {
  116. // array.add(new CodeName("livePlace2","患者现住址有冗余重复!"));
  117. // }
  118. // }
  119. //
  120. // try {
  121. // byte[] livePlaceBytes = info.getLivePlace().getBytes("GBK");
  122. // if (livePlaceBytes.length > 32) {
  123. // array.add(new CodeName("livePlace", "患者现住址不能超过32个字节,当前字节数为" + livePlaceBytes.length + "(1汉字=2字节,1字母或数字=1字节)!"));
  124. // }
  125. // } catch (Exception e) {
  126. // log.error("分析患者现住址长度出现异常", e);
  127. // }
  128. if (StringUtil.invalidValue(info.getPhone())) {
  129. array.add(new CodeName("phone","患者电话不能为空!"));
  130. }
  131. if (StringUtil.invalidValue(info.getHkPlaceName())) {
  132. array.add(new CodeName("hkPlaceName","患者户口地址不能为空!"));
  133. }
  134. // 移除工作单位及地址不能为空验证
  135. // if (StringUtil.invalidValue(info.getUnitName()) || StringUtil.invalidValue(info.getUnitPlace())) {
  136. // array.add(new CodeName("unitName","患者工作单位及地址不能为空!"));
  137. // }
  138. // 移除单位电话不能为空验证
  139. // if (StringUtil.isBlank(info.getUnitPhone())) {
  140. // array.add(new CodeName("unitPhone","患者单位电话不能为空!"));
  141. // }
  142. // 移除单位邮编不能为空验证
  143. // if (StringUtil.isBlank(info.getUnitZipCode()) || info.getUnitZipCode().contains("-")) {
  144. // array.add(new CodeName("unitZipCode", "患者工作单位邮编不能为空!"));
  145. // }
  146. if (StringUtil.isBlank(info.getAddrZipCode()) || info.getAddrZipCode().contains("-")) {
  147. array.add(new CodeName("addrZipCode", "患者现住址邮编不能为空!"));
  148. }
  149. if (StringUtil.isBlank(info.getHkZipCode()) || info.getHkZipCode().contains("-")) {
  150. array.add(new CodeName("hkZipCode", "患者户口邮编不能为空!"));
  151. }
  152. if (StringUtil.invalidValue(info.getContactName())) {
  153. array.add(new CodeName("contactName","患者联系人姓名不能为空!"));
  154. }
  155. if (StringUtil.invalidValue(info.getContactRelation())) {
  156. array.add(new CodeName("contactRelation","患者联系人关系不能为空!"));
  157. }
  158. if (StringUtil.invalidValue(info.getContactAddrName())) {
  159. array.add(new CodeName("contactAddrName","患者联系人地址不能为空!"));
  160. }
  161. // 移除联系人地址字数限制验证,保留非空验证
  162. // else {
  163. // if (info.getContactAddrName().length() > 16) {
  164. // array.add(new CodeName("contactAddrName", "患者联系人地址不能超过16个汉字!"));
  165. // }
  166. // }
  167. if (StringUtil.invalidValue(info.getContactPhone())) {
  168. array.add(new CodeName("contactPhone","患者联系人电话不能为空!"));
  169. }
  170. if (StringUtil.invalidValue(info.getZyAdmissWay())) {
  171. array.add(new CodeName("zyAdmissWay","患者入院途径不能为空!"));
  172. }
  173. if (null == info.getAdmissDate()) {
  174. array.add(new CodeName("admissDate","患者入院时间不能为空!"));
  175. }
  176. if (StringUtil.invalidValue(info.getAdmissDept())) {
  177. array.add(new CodeName("admissDept","患者入院科别不能为空!"));
  178. }
  179. if (StringUtil.invalidValue(info.getHasSurgery())) {
  180. array.add(new CodeName("hasSurgery","患者是否手术不能为空!"));
  181. }
  182. if (null == info.getDismissDate()) {
  183. array.add(new CodeName("dismissDate","患者出院时间不能为空!"));
  184. }
  185. if (StringUtil.invalidValue(info.getDismissDept())) {
  186. array.add(new CodeName("dismissDept","患者出院科别不能为空!"));
  187. }
  188. if (StringUtil.invalidValue(info.getAdmissDays())) {
  189. array.add(new CodeName("admissDays","患者住院天数不能为空!"));
  190. }
  191. if (StringUtil.isBlank(info.getClinicDiagCode()) || StringUtil.isBlank(info.getClinicDiagStr())) {
  192. array.add(new CodeName("clinicDiag", "患者门(急)诊诊断需要填写标准诊断,请补充。"));
  193. } else {
  194. validateClinicDiagnose(info.getClinicDiagCode(), array);
  195. }
  196. CaseFrontsheetDisdiag disdiag = info.getDisdiagList().get(0);
  197. if (StringUtil.isBlank(disdiag.getName())) {
  198. array.add(new CodeName("disdiagMain","患者主要诊断不能为空!"));
  199. } else {
  200. // validateMainDiagnose(disdiag.getCode(), array);
  201. }
  202. if (null == info.getDisdiagList().get(0).getAdmissStatus()) {
  203. array.add(new CodeName("disdiagMainAdmStatus","患者主要诊断入院病情不能为空!"));
  204. }
  205. if (StringUtil.invalidValue(info.getAllergy())) {
  206. array.add(new CodeName("allergy","患者有无药物过敏不能为空!"));
  207. }
  208. if (StringUtil.isBlank(info.getBloodType())) {
  209. array.add(new CodeName("bloodType","患者ABO血型不能为空!"));
  210. }
  211. if (StringUtil.isBlank(info.getRh())) {
  212. array.add(new CodeName("rh","患者Rh血型不能为空!"));
  213. }
  214. if (StringUtil.invalidValue(info.getDeptLeader())) {
  215. array.add(new CodeName("deptLeaderName","科主任不能为空!"));
  216. }
  217. if (StringUtil.invalidValue(info.getLeaderDoctor())) {
  218. array.add(new CodeName("leaderDoctorName","主任(副主任)医师不能为空!"));
  219. }
  220. if (StringUtil.invalidValue(info.getMainDoctor())) {
  221. array.add(new CodeName("mainDoctorName","主治医师不能为空!"));
  222. }
  223. if (StringUtil.invalidValue(info.getAdmissDoctor())) {
  224. array.add(new CodeName("admissDoctorName","住院医师不能为空!"));
  225. }
  226. if (StringUtil.invalidValue(info.getDutyNurse())) {
  227. array.add(new CodeName("dutyNurseName","责任护士不能为空!"));
  228. }
  229. if (StringUtil.invalidValue(info.getCoder())) {
  230. array.add(new CodeName("coderName","编码员不能为空!"));
  231. }
  232. if (StringUtil.invalidValue(info.getQualityControlLevel())) {
  233. array.add(new CodeName("qualityControlLevel","病案质量不能为空!"));
  234. }
  235. if (StringUtil.invalidValue(info.getZyDismissWay())) {
  236. array.add(new CodeName("zyDismissWay","患者离院方式不能为空!"));
  237. }
  238. if (StringUtil.invalidValue(info.getAdmissAgainInOneMonth())) {
  239. array.add(new CodeName("admissAgainInOneMonth","患者是否有出院31天内再住院计划不能为空!"));
  240. }
  241. if (StringUtil.invalidValue(info.getQualityControlDoctor())) {
  242. array.add(new CodeName("qualityControlDoctorName","质控医生不能为空!"));
  243. }
  244. if (StringUtil.invalidValue(info.getQualityControlNurse())) {
  245. array.add(new CodeName("qualityControlNurseName","质控护士不能为空!"));
  246. }
  247. if (StringUtil.invalidValue(info.getCaseClassification())) {
  248. array.add(new CodeName("caseClassification","病例分型不能为空!"));
  249. }
  250. // if (StringUtil.invalidValue(info.getHasIcu())) {
  251. // array.add(new CodeName("hasIcu","实施重症监护不能为空!"));
  252. // }
  253. if (StringUtil.isBlank(info.getMonopathyManagement())) {
  254. array.add(new CodeName("monopathyManagement","单病种管理不能为空!"));
  255. }
  256. if (StringUtil.isBlank(info.getClinicalPathwayManagement())) {
  257. array.add(new CodeName("clinicalPathwayManagement","实施临床路径管理不能为空!"));
  258. }
  259. if (StringUtil.isBlank(info.getUseAntibiotic())) {
  260. array.add(new CodeName("useAntibiotic","抗生素使用不能为空!"));
  261. }
  262. if (StringUtil.isBlank(info.getBacilliculture())) {
  263. array.add(new CodeName("bacilliculture","细菌培养标本送检不能为空!"));
  264. }
  265. if (zipCodeLengthWrong(info.getAddrZipCode())) {
  266. array.add(new CodeName("addrZipCode","现住址邮编长度错误!"));
  267. }
  268. // 移除邮编长度限制
  269. // if (zipCodeLengthWrong(info.getHkZipCode())) {
  270. // array.add(new CodeName("hkZipCode","户口地址邮编长度错误!"));
  271. // }
  272. // if (zipCodeLengthWrong(info.getUnitZipCode())) {
  273. // array.add(new CodeName("unitZipCode","工作地址邮编错误!"));
  274. // }
  275. if (phoneLengthWrong(info.getPhone())) {
  276. array.add(new CodeName("phone","患者电话号码长度错误!"));
  277. }
  278. if (phoneLengthWrong(info.getContactPhone())) {
  279. array.add(new CodeName("contactPhone","联系人电话号码长度错误!"));
  280. }
  281. // 移除单位电话长度限制
  282. // if (phoneLengthWrong(info.getUnitPhone())) {
  283. // array.add(new CodeName("unitPhone","工作单位电话长度错误!"));
  284. // }
  285. if (DateUtil.daysBetween(info.getDismissDate(), info.getAdmissDate()) < 0) {
  286. array.add(new CodeName("dismissDate","出院时间不能小于入院时间!"));
  287. }
  288. if (DateUtil.daysBetween(info.getBirthDate(), info.getAdmissDate()) > 0) {
  289. array.add(new CodeName("birthDate","出生时间不能大于入院时间!"));
  290. }
  291. if (DateUtil.daysBetween(info.getQualityControlDate(), info.getDismissDate()) < 0) {
  292. array.add(new CodeName("qualityControlDate","质控日期不能小于出院日期!"));
  293. }
  294. if (DateUtil.daysBetween(info.getQualityControlDate(), info.getDismissDate()) > 7) {
  295. array.add(new CodeName("qualityControlDate","质控日期不能大于出院7天!"));
  296. }
  297. // 移除户口地址和单位地址长度限制
  298. // if (StringUtil.notBlank(info.getHkPlaceName()) && info.getHkPlaceName().length() > 10) {
  299. // array.add(new CodeName("hkPlaceName", "患者户口地址不能超过10个汉字!"));
  300. // }
  301. // if (StringUtil.notBlank(info.getUnitPlace()) && info.getUnitPlace().length() > 16) {
  302. // array.add(new CodeName("unitPlace", "患者单位地址不能超过16个汉字!"));
  303. // }
  304. if (null != info.getAgeDays() && !isPositiveDigital(String.valueOf(info.getAgeDays()))) {
  305. array.add(new CodeName("ageDays", "不足1周岁婴儿的年龄请填写正整数。"));
  306. }
  307. if (null != info.getAgeDays() && info.getAgeDays() <= 28) {
  308. if (null == info.getNewBornWeight1() || null == info.getNewBornAdmissWeight()) {
  309. array.add(new CodeName("newBornWeight","请填写新生儿出生体重和入院体重!"));
  310. }
  311. if (null != info.getNewBornWeight1() && info.getNewBornWeight1() < 1000) {
  312. array.add(new CodeName("newBornWeight","请填写合理的新生儿出生体重(不得少于1000g)!"));
  313. }
  314. if (null != info.getNewBornAdmissWeight() && info.getNewBornAdmissWeight() < 1000) {
  315. array.add(new CodeName("newBornAdmissWeight","请填写合理的新生儿入院体重(不得少于1000g)!"));
  316. }
  317. if (StringUtil.invalidValue(info.getXxeApgar())) {
  318. array.add(new CodeName("xxeApgar","新生儿Apgar评分不能为空!"));
  319. }
  320. }
  321. if (null != info.getAgeDays() && info.getAgeDays() > 28) {
  322. if (null != info.getNewBornWeight1() || null != info.getNewBornAdmissWeight()) {
  323. array.add(new CodeName("newBornWeight","非新生儿请保持新生信息为空!"));
  324. }
  325. }
  326. if (null == info.getAgeDays() || 0 == info.getAgeDays()) {
  327. if (null != info.getNewBornWeight1() || null != info.getNewBornAdmissWeight()) {
  328. array.add(new CodeName("ageDays","新生儿年龄不能为空!"));
  329. }
  330. }
  331. return connectedVerify(array, info);
  332. }
  333. private List<CodeName> connectedVerify(List<CodeName> array, CaseFrontsheetMain info) {
  334. if (StringUtil.notBlank(info.getMarriage())) {
  335. // if (null != info.getAge() && info.getAge() < 20 && !info.getMarriage().equals("1")) {
  336. // array.add(new CodeName("marriage", "患者年龄小于20周岁,婚姻状况须填未婚。"));
  337. // }
  338. if (info.getMarriage().equals("1") || info.getMarriage().equals("3") || info.getMarriage().equals("4")) {
  339. if (StringUtil.notBlank(info.getContactRelation()) &&
  340. info.getContactRelation().equals("1")) {
  341. array.add(new CodeName("contactRelation", "当婚姻状况为未婚、丧偶、离婚时,患者联系人关系不允许为配偶!"));
  342. }
  343. }
  344. }
  345. if (StringUtil.notBlank(info.getZyDismissWay())) {
  346. if ("1".equals(info.getZyDismissWay()) || "2".equals(info.getZyDismissWay())) {
  347. if (StringUtil.invalidValue(info.getDismissDestination())) {
  348. array.add(new CodeName("dismissDestination","患者转入医疗机构不能为空!"));
  349. }
  350. }
  351. if ("3".equals(info.getZyDismissWay())) {
  352. if (StringUtil.invalidValue(info.getFyzlyyy())) {
  353. array.add(new CodeName("fyzlyyy", "非医嘱离院原因不能为空!"));
  354. }
  355. } else {
  356. info.setFyzlyyy(null);
  357. }
  358. }
  359. if (StringUtil.notBlank(info.getHasSurgery()) && "0".equals(info.getHasSurgery()) && !"0".equals(info.getDiagConform3())) {
  360. array.add(new CodeName("diagConform3","无手术时,诊断符合情况中的术前与术后需要为【未做】!"));
  361. }
  362. if (StringUtil.notBlank(info.getHasSurgery())) {
  363. if ("1".equals(info.getHasSurgery()) || "2".equals(info.getHasSurgery()) || "3".equals(info.getHasSurgery())) {
  364. if ("0".equals(info.getDiagConform3())) {
  365. array.add(new CodeName("diagConform3","有手术时,诊断符合情况中的术前与术后不可为【未做】!"));
  366. }
  367. }
  368. }
  369. if (StringUtil.notBlank(info.getZyDismissWay()) && "4".equals(info.getZyDismissWay())) {
  370. if (StringUtil.isBlank(info.getAutopsy())) {
  371. array.add(new CodeName("autopsy", "离院方式为死亡时,尸检不能为空!"));
  372. }
  373. }
  374. if (StringUtil.validValue(info.getAutopsy()) && !"".equals(info.getAutopsy())) {
  375. if (!"4".equals(info.getZyDismissWay())) {
  376. array.add(new CodeName("zyDismissWay","尸检不为空时,需要离院方式为死亡!"));
  377. }
  378. }
  379. boolean hasAnaesthesia = false;
  380. boolean hasAnaesthesiaor = false;
  381. for (CaseFrontsheetSurgery surgery : info.getSurgeryList()) {
  382. checkSurgery(array, surgery, info.getAdmissDate(), info.getDismissDate());
  383. if (StringUtil.notBlank(surgery.getAnaesthesia())) {
  384. hasAnaesthesia = true;
  385. }
  386. if (StringUtil.notBlank(surgery.getAnaesthesiaor())) {
  387. hasAnaesthesiaor = true;
  388. }
  389. }
  390. if (DecimalUtil.biggerThanZero(info.getAnesthetizeFee())) {
  391. if (ListUtil.isBlank(info.getSurgeryList())) {
  392. array.add(new CodeName("surgeryMain", "患者有麻醉费,手术列表不能为空!"));
  393. } else {
  394. if (!hasAnaesthesia) {
  395. array.add(new CodeName("surgeryMain", "患者有麻醉费,麻醉方式不能为空!"));
  396. }
  397. if (!hasAnaesthesiaor) {
  398. array.add(new CodeName("surgeryMain", "患者有麻醉费,麻醉医师不能为空!"));
  399. }
  400. }
  401. }
  402. if (needPathologicDiag(info.getDisdiagList().get(0).getCode()) &&
  403. (StringUtil.isBlank(info.getPathologicDiagStr()) || StringUtil.isBlank(info.getPathologicDiagCode()))) {
  404. array.add(new CodeName("pathologicDiagCode","根据患者出院主要诊断,病理诊断不能为空!"));
  405. }
  406. // if (StringUtil.validValue(info.getHasIcu()) && "2".equals(info.getHasIcu()) &&
  407. // (StringUtil.invalidValue(info.getIcuDays()) || StringUtil.invalidValue(info.getIcuHours()))) {
  408. // array.add(new CodeName("icuHours","患者ICU时间不能为空!"));
  409. // }
  410. if (StringUtil.notBlank(info.getHasSurgery()) && hasSurgery(info.getHasSurgery()) &&
  411. StringUtil.isBlank(info.getSurgeryList().get(0).getName())) {
  412. array.add(new CodeName("surgeryMain","患者有手术时,手术列表不能为空!"));
  413. }
  414. if (StringUtil.validValue(info.getAllergy()) && "2".equals(info.getAllergy()) && StringUtil.invalidValue(info.getAllergicMedicine())) {
  415. array.add(new CodeName("allergicMedicine","患者有药物过敏时,过敏药物名称不能为空!"));
  416. }
  417. if (DecimalUtil.biggerThanZero(info.getPathologicDiagFee()) && StringUtil.invalidValue(info.getBlh())) {
  418. array.add(new CodeName("blh","患者有病理诊断费,病理号不能为空!"));
  419. }
  420. if (DecimalUtil.biggerThanZero(info.getSurgeryFee()) && StringUtil.isBlank(info.getSurgeryList().get(0).getName())) {
  421. array.add(new CodeName("surgeryMain","患者有手术费,手术列表不能为空!"));
  422. }
  423. if (needHurtReason(info.getDisdiagList().get(0).getCode()) &&
  424. (StringUtil.invalidValue(info.getHurtReasonName()) || StringUtil.invalidValue(info.getHurtReasonCode()))) {
  425. array.add(new CodeName("hurtReasonName","根据患者出院主要诊断,损伤中毒诊断不能为空!"));
  426. }
  427. if (StringUtil.notBlank(info.getBloodType())) {
  428. if (!"5".equals(info.getBloodType()) && !"6".equals(info.getBloodType())) {
  429. if (!"1".equals(info.getRh()) && !"2".equals(info.getRh())) {
  430. array.add(new CodeName("rh","患者血型确定时,Rh血型应为阴或阳!"));
  431. }
  432. }
  433. }
  434. if (hasDuplicateDiag(info.getDisdiagList())) {
  435. array.add(new CodeName("diagTable","出院诊断不能存在相同的诊断编码!"));
  436. }
  437. if (invalidBirthDiag(info.getDisdiagList())) {
  438. array.add(new CodeName("diagTable", "当主要诊断或者其它诊断编码出现O80-O84编码,且无流产结局时,其它诊断编码必须有分娩结局编码Z37。"));
  439. }
  440. if (hasSameSurgeryInOneDay(info.getSurgeryList())) {
  441. array.add(new CodeName("surgeryTable","同一天不能有相同的手术!"));
  442. }
  443. if (surgeryDateWrong(info.getSurgeryList(), info.getAdmissDate(), info.getDismissDate())) {
  444. array.add(new CodeName("surgeryTable","手术时间必须在入院时间24小时之前和出院时间之间!"));
  445. }
  446. if ((StringUtil.notBlank(info.getBloodType()) && ("5".equals(info.getBloodType()) || "6".equals(info.getBloodType()))) &&
  447. (StringUtil.notBlank(info.getRh()) && !"0".equals(info.getRh()) && !"3".equals(info.getRh()))) {
  448. array.add(new CodeName("rh","患者血型不确定时,Rh血型应为不详或未查!"));
  449. }
  450. if (StringUtil.notBlank(info.getRescueTimes()) && Integer.parseInt(info.getRescueTimes()) < 0) {
  451. array.add(new CodeName("rescueTimes","抢救次数不能为负数!"));
  452. }
  453. if (Integer.parseInt(info.getRescueTimes()) < Integer.parseInt(info.getRescueSuccessTimes())) {
  454. array.add(new CodeName("rescueSuccessTimes","抢救成功次数不能大于抢救次数!"));
  455. }
  456. if (Integer.parseInt(info.getRescueTimes()) - Integer.parseInt(info.getRescueSuccessTimes()) > 1) {
  457. array.add(new CodeName("rescueSuccessTimes","抢救成功次数不能少于抢救次数两次!"));
  458. }
  459. return array;
  460. }
  461. private boolean hasSurgeryFee(String str) {
  462. if (StringUtil.invalidValue(str)) {
  463. return false;
  464. }
  465. return Float.parseFloat(str) > 0;
  466. }
  467. private boolean hasSurgery(String flag) {
  468. return "1".equals(flag) || "2".equals(flag) || "3".equals(flag);
  469. }
  470. private boolean isHighLevelSurgery(String level) {
  471. return StringUtil.notBlank(level) && ("3".equals(level) || "4".equals(level));
  472. }
  473. private void checkSurgery(List<CodeName> array, CaseFrontsheetSurgery surgery,
  474. Date admissDate, Date dismissDate) {
  475. if (StringUtil.isBlank(surgery.getName())) {
  476. return;
  477. }
  478. if (surgery.getType() == 1) {
  479. if (StringUtil.isBlank(surgery.getAnaesthesia())) {
  480. array.add(new CodeName("surgeryTable","手术" + surgery.getNo() + ",麻醉方式不能为空!"));
  481. }
  482. if (StringUtil.isBlank(surgery.getAnaesthesiaor())) {
  483. array.add(new CodeName("surgeryTable","手术" + surgery.getNo() + ",麻醉医师不能为空!"));
  484. }
  485. }
  486. if (StringUtil.isBlank(surgery.getOperator())) {
  487. array.add(new CodeName("surgeryTable","手术" + surgery.getNo() + ",术者不能为空!"));
  488. }
  489. if (surgery.getType() < 3 && StringUtil.isBlank(surgery.getLevel())) {
  490. array.add(new CodeName("surgeryTable","手术" + surgery.getNo() + "手术操作编码为介入治疗或手术时,手术级别不能为空!"));
  491. }
  492. if (isHighLevelSurgery(surgery.getLevel())) {
  493. if (StringUtil.isBlank(surgery.getAssistantOne())) {
  494. array.add(new CodeName("surgeryTable","手术" + surgery.getNo() + ",三、四级手术I助不能为空!"));
  495. }
  496. if (StringUtil.isBlank(surgery.getCutHeal())) {
  497. array.add(new CodeName("surgeryTable","手术" + surgery.getNo() + ",三、四级手术切口愈合等级不能为空!"));
  498. }
  499. if (StringUtil.isBlank(surgery.getAssistantTwo())) {
  500. array.add(new CodeName("surgeryTable","手术" + surgery.getNo() + ",三、四级手术II助不能为空!"));
  501. }
  502. }
  503. if (needAnstTimeButNotPresent(surgery)) {
  504. array.add(new CodeName("surgeryTable","手术" + surgery.getNo() + ",麻醉开始时间和结束时间不能为空!"));
  505. }
  506. List<String> msgs = logicalSurgeryTime(admissDate, dismissDate, surgery.getDate(), surgery.getOpEndDate(),
  507. surgery.getAnstStartDate(), surgery.getAnstEndDate());
  508. for (String msg : msgs) {
  509. array.add(new CodeName("surgeryTable", "手术" + surgery.getNo() + "," + msg));
  510. }
  511. }
  512. private boolean needAnstTimeButNotPresent(CaseFrontsheetSurgery surgery) {
  513. if (StringUtil.isBlank(surgery.getAnaesthesia()) || surgery.getAnaesthesia().equals("23")
  514. || surgery.getAnaesthesia().equals("29")) {
  515. return false;
  516. }
  517. return StringUtil.notBlank(surgery.getAnaesthesiaor()) &&
  518. (null == surgery.getAnstStartDate() || null == surgery.getAnstEndDate());
  519. }
  520. public static List<String> logicalSurgeryTime(Date admDate, Date disDate,
  521. Date opStart, Date opEnd, Date anstStart, Date anstEnd) {
  522. List<String> errors = new ArrayList<>();
  523. if (null == opStart) {
  524. errors.add("手术开始时间不能为空。");
  525. }
  526. if (null == opEnd) {
  527. errors.add("手术结束时间不能为空。");
  528. }
  529. if (null != opStart && null != admDate) {
  530. long admstamp = admDate.getTime() - (24 * 60 * 60 * 1000);
  531. long srgstamp = opStart.getTime();
  532. if (admstamp > srgstamp) {
  533. errors.add("手术开始时间不能早于入院时间前24小时");
  534. }
  535. }
  536. if (null != opStart && null != disDate && opStart.after(disDate)) {
  537. errors.add("手术开始时间不能晚于出院时间。");
  538. }
  539. if (null != opStart && null != opEnd && opEnd.before(opStart)) {
  540. errors.add("手术开始时间不能晚于手术结束时间。");
  541. }
  542. if (null != anstStart && null != opStart && anstStart.after(opStart)) {
  543. errors.add("麻醉开始时间不能晚于手术开始时间。");
  544. }
  545. if (null != anstStart && null != opEnd && anstStart.after(opEnd)) {
  546. errors.add("麻醉开始时间不能晚于手术结束时间。");
  547. }
  548. if (null != anstEnd && null != opEnd && anstEnd.before(opEnd)) {
  549. errors.add("麻醉结束时间不能早于手术结束时间。");
  550. }
  551. if (null != anstEnd && null != opStart && anstEnd.before(opStart)) {
  552. errors.add("麻醉结束时间不能早于手术开始时间。");
  553. }
  554. return errors;
  555. }
  556. private void validateClinicDiagnose(String code, List<CodeName> errors) {
  557. String fstLetter = code.substring(0, 1).toUpperCase();
  558. if (isNumeric(fstLetter)) {
  559. errors.add(new CodeName("clinicDiag", "门(急)诊诊断编码范围应为:A~U开头和Z开头的编码;不包括字母V、W、X、Y开头的编码。"));
  560. return;
  561. }
  562. if (fstLetter.equals("V") || fstLetter.equals("W") ||
  563. fstLetter.equals("X") || fstLetter.equals("Y")) {
  564. errors.add(new CodeName("clinicDiag", "门(急)诊诊断编码范围应为:A~U开头和Z开头的编码;不包括字母V、W、X、Y开头的编码。"));
  565. }
  566. }
  567. private void validateMainDiagnose(String code, List<CodeName> errors) {
  568. if (StringUtil.isBlank(code)) {
  569. return;
  570. }
  571. String header = code.substring(0, 3);
  572. String tail = header.substring(1);
  573. if (isNumeric(tail)) {
  574. int tailNumber = Integer.parseInt(tail);
  575. if (code.charAt(0) == 'R' && tailNumber <= 99) {
  576. errors.add(new CodeName("disdiagMain", "症状体征异常情况不能作为患者主要诊断!"));
  577. }
  578. }
  579. if (code.startsWith("B95.") || code.startsWith("B96.") || code.startsWith("B97.")) {
  580. errors.add(new CodeName("disdiagMain", "某些传染和寄生虫病编码中的细菌、病毒和其他传染性病原体(B95-B97)不能作为患者主要诊断!"));
  581. }
  582. if (code.startsWith("T31.") || code.startsWith("T32.")) {
  583. errors.add(new CodeName("disdiagMain", "烧伤及腐蚀面积不能作为患者主要诊断!"));
  584. }
  585. if (code.startsWith("Z37.") || code.startsWith("Z38.")) {
  586. errors.add(new CodeName("disdiagMain", "分娩结局不能作为患者主要诊断!"));
  587. }
  588. if (code.startsWith("Z85.")) {
  589. errors.add(new CodeName("disdiagMain", "恶性肿瘤个人史不能作为患者主要诊断!"));
  590. }
  591. if (code.startsWith("Z86.") || code.startsWith("Z87.")) {
  592. errors.add(new CodeName("disdiagMain", "既往病史不能作为患者主要诊断!"));
  593. }
  594. if (code.startsWith("Z93.")) {
  595. errors.add(new CodeName("disdiagMain", "人工造口状态不能作为患者主要诊断!"));
  596. }
  597. if (code.startsWith("Z98.")) {
  598. errors.add(new CodeName("disdiagMain", "手术后状态不能作为患者主要诊断!"));
  599. }
  600. }
  601. private boolean isNumeric(String str){
  602. Pattern pattern = Pattern.compile("[0-9]*");
  603. return pattern.matcher(str).matches();
  604. }
  605. private boolean needPathologicDiag(String diag) {
  606. if (StringUtil.invalidValue(diag)) {
  607. return false;
  608. }
  609. final char firstLetter = diag.toUpperCase().charAt(0);
  610. if (firstLetter != 'C' && firstLetter != 'D') {
  611. return false;
  612. }
  613. final String diagBase = diag.substring(1, 3);
  614. final int code;
  615. try {
  616. code = Integer.parseInt(diagBase);
  617. } catch (NumberFormatException e) {
  618. return false;
  619. }
  620. if (firstLetter == 'C') {
  621. return code >= 0 && code <= 97;
  622. } else {
  623. return (code >= 0 && code <= 9) || (code >= 10 && code <= 36) || (code >= 37 && code <= 48);
  624. }
  625. }
  626. private boolean needHurtReason(String diag) {
  627. if (StringUtil.invalidValue(diag)) {
  628. return false;
  629. }
  630. diag = diag.toUpperCase();
  631. if (diag.startsWith("SY")) {
  632. return false;
  633. }
  634. final char firstLetter = diag.charAt(0);
  635. return firstLetter == 'S' || firstLetter == 'T';
  636. }
  637. private boolean hasDuplicateDiag(List<CaseFrontsheetDisdiag> disdiags) {
  638. Map<String, String> map = new HashMap<>(Capacity.DEFAULT);
  639. for (CaseFrontsheetDisdiag diag : disdiags) {
  640. if (StringUtil.validValue(diag.getCode())) {
  641. if (map.containsKey(diag.getCode())) {
  642. return true;
  643. }
  644. map.put(diag.getCode(), diag.getName());
  645. }
  646. }
  647. return false;
  648. }
  649. /**
  650. * 当主要诊断或者其它诊断编码出现O80-O84编码,且无流产结局编码出现O00-O08编码时,其它诊断编码必须有分娩结局编码Z37
  651. * */
  652. private boolean invalidBirthDiag(List<CaseFrontsheetDisdiag> disdiags) {
  653. boolean isBirth = false;
  654. boolean isAbortion = false;
  655. boolean isDelivered = false;
  656. for (CaseFrontsheetDisdiag diag : disdiags) {
  657. String code = diag.getCode();
  658. if (StringUtil.isBlank(code)) {
  659. continue;
  660. }
  661. if (code.startsWith("O80.") || code.startsWith("O81.") || code.startsWith("O82.")
  662. || code.startsWith("O83.") || code.startsWith("O84.")) {
  663. isBirth = true;
  664. }
  665. if (code.startsWith("O00.") || code.startsWith("O01.") || code.startsWith("O02.")
  666. || code.startsWith("O03.") || code.startsWith("O04.") || code.startsWith("O05.")
  667. || code.startsWith("O06.") || code.startsWith("O07.") || code.startsWith("O08.")) {
  668. isAbortion = true;
  669. }
  670. if (code.startsWith("Z37.")) {
  671. isDelivered = true;
  672. }
  673. }
  674. return isBirth && !isAbortion && !isDelivered;
  675. }
  676. private boolean hasSameSurgeryInOneDay(List<CaseFrontsheetSurgery> surgeries) {
  677. Map<String, String> map = new HashMap<>(Capacity.DEFAULT);
  678. for (CaseFrontsheetSurgery surgery : surgeries) {
  679. if (StringUtil.validValue(surgery.getCode())) {
  680. if (map.containsKey(surgery.getCode() + DateUtil.formatDatetime(surgery.getDate(), "yyyy-MM-dd HH:mm:ss"))) {
  681. return true;
  682. }
  683. map.put(surgery.getCode() + DateUtil.formatDatetime(surgery.getDate(), "yyyy-MM-dd HH:mm:ss"), surgery.getCode());
  684. }
  685. }
  686. return false;
  687. }
  688. private boolean zipCodeLengthWrong(String zipCode) {
  689. return StringUtil.notBlank(zipCode) && zipCode.length() != 6;
  690. }
  691. private boolean surgeryDateWrong(List<CaseFrontsheetSurgery> surgeries, Date admissDate, Date outmissDate) {
  692. if (null == outmissDate) {
  693. return false;
  694. }
  695. long admstamp = admissDate.getTime() - (24 * 60 * 60 * 1000);
  696. long disstamp = outmissDate.getTime();
  697. for (CaseFrontsheetSurgery item : surgeries) {
  698. if (StringUtil.isBlank(item.getCode())) {
  699. continue;
  700. }
  701. if (StringUtil.notBlank(item.getCode()) && null == item.getDate()) {
  702. return true;
  703. }
  704. long srgstamp = item.getDate().getTime();
  705. if (admstamp > srgstamp || srgstamp > disstamp) {
  706. return true;
  707. }
  708. }
  709. return false;
  710. }
  711. private boolean phoneLengthWrong(String phone) {
  712. if (StringUtil.isBlank(phone)) {
  713. return false;
  714. }
  715. return phone.length() != 11 && phone.length() != 12 && phone.length() != 8;
  716. }
  717. private boolean isPositiveDigital(String string) {
  718. String regEx1 = "\\d+";
  719. Pattern p;
  720. Matcher m;
  721. p = Pattern.compile(regEx1);
  722. m = p.matcher(string);
  723. return m.matches();
  724. }
  725. }