AppointmentService.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. package thyyxxk.wxservice_server.service;
  2. import com.alibaba.fastjson.JSONArray;
  3. import com.alibaba.fastjson.JSONObject;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.beans.factory.annotation.Value;
  7. import org.springframework.stereotype.Service;
  8. import org.springframework.web.client.RestTemplate;
  9. import thyyxxk.wxservice_server.config.exception.ExceptionEnum;
  10. import thyyxxk.wxservice_server.constant.Constants;
  11. import thyyxxk.wxservice_server.constant.Gender;
  12. import thyyxxk.wxservice_server.dao.AppointmentDao;
  13. import thyyxxk.wxservice_server.entity.BriefPatInfo;
  14. import thyyxxk.wxservice_server.entity.ResultVo;
  15. import thyyxxk.wxservice_server.entity.appointment.*;
  16. import thyyxxk.wxservice_server.entity.hrgresponse.SourcesResponse;
  17. import thyyxxk.wxservice_server.entity.hrgresponse.HrgCommonResponse;
  18. import thyyxxk.wxservice_server.entity.hrgresponse.MzClassResponse;
  19. import thyyxxk.wxservice_server.utils.*;
  20. import java.text.SimpleDateFormat;
  21. import java.util.*;
  22. /**
  23. * @author dj
  24. */
  25. @Slf4j
  26. @Service
  27. public class AppointmentService {
  28. private static final List<MzClass> mzClasses = new ArrayList<>();
  29. private final AppointmentDao dao;
  30. private final RedisLikeService redis;
  31. private final ElectronicHealthCardService healthCardService;
  32. private final WxRefundService wxRefundService;
  33. @Value("${hrgApiUrl}")
  34. private String hrgApiUrl;
  35. @Autowired
  36. public AppointmentService(AppointmentDao dao, RedisLikeService redis, ElectronicHealthCardService healthCardService, WxRefundService wxRefundService) {
  37. this.dao = dao;
  38. this.redis = redis;
  39. this.healthCardService = healthCardService;
  40. this.wxRefundService = wxRefundService;
  41. }
  42. public ResultVo<List<MzClass>> getAllDepartments() {
  43. if (ListUtil.notEmpty(mzClasses)) {
  44. return ResultVoUtil.success(mzClasses);
  45. }
  46. log.info("重新获取门诊科室并缓存。");
  47. List<Map<String, Object>> tempMzClasses = fetchMzClassesFromApi();
  48. if (null == tempMzClasses) {
  49. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "获取科室分类失败,请联系服务中心。");
  50. }
  51. for (Map<String, Object> mzClass : tempMzClasses) {
  52. fetchMzDepartmentsByMzClasses(mzClass);
  53. }
  54. return ResultVoUtil.success(mzClasses);
  55. }
  56. private List<Map<String, Object>> fetchMzClassesFromApi() {
  57. RestTemplate template = new RestTemplate();
  58. MzClassResponse response = template.getForObject(hrgApiUrl + "/getMzClass", MzClassResponse.class);
  59. if (null == response || -1 == response.getResultCode()) {
  60. return null;
  61. }
  62. return response.getData();
  63. }
  64. private void fetchMzDepartmentsByMzClasses(Map<String, Object> mzClass) {
  65. String mzClassCode = mzClass.get("code").toString();
  66. JSONObject params = JSONObject.parseObject("{\"mzClass\": \"" + mzClassCode + "\"}");
  67. MzClassResponse tempMzDepartments = new RestTemplate().postForObject(hrgApiUrl + "/getUnitCodeByMzClass",
  68. params, MzClassResponse.class);
  69. if (null != tempMzDepartments && tempMzDepartments.getResultCode() == 0) {
  70. List<MzDept> children = new ArrayList<>();
  71. for (Map<String, Object> child : tempMzDepartments.getData()) {
  72. MzDept childDepartment = new MzDept(child.get("code").toString(), child.get("name").toString());
  73. List<Map<String, Object>> grandChildrenMap = CastUtil.cast(child.get("children"));
  74. if (null != grandChildrenMap && grandChildrenMap.size() > 0) {
  75. List<MzDept> grandChildren = new ArrayList<>();
  76. for (Map<String, Object> grandChild : grandChildrenMap) {
  77. grandChildren.add(new MzDept(grandChild.get("code").toString(), grandChild.get("name").toString()));
  78. }
  79. childDepartment.setChildren(grandChildren);
  80. }
  81. children.add(childDepartment);
  82. }
  83. mzClasses.add(new MzClass(mzClassCode, mzClass.get("name").toString(), children));
  84. }
  85. }
  86. public ResultVo<String> refreshMzClasses() {
  87. mzClasses.clear();
  88. log.info("门诊科室缓存已重置。");
  89. return ResultVoUtil.success("门诊科室缓存已重置。");
  90. }
  91. public ResultVo<Integer[]> getSourcesByDate(GetSourcesByDateParam param) {
  92. Integer[] sourceArray = new Integer[7];
  93. RestTemplate template = new RestTemplate();
  94. Calendar calendar = Calendar.getInstance();
  95. SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
  96. for (int i = 0; i < 7; i++) {
  97. sourceArray[i] = 0;
  98. int addNum = i == 0 ? 0 : 1;
  99. calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) + addNum);
  100. String date = format.format(calendar.getTime());
  101. String url = String.format(hrgApiUrl + "/getDoctorByDateAndDept?requestDay=%s&unitCode=%s", date, param.getDept());
  102. SourcesResponse hrgResponse = template.getForObject(url, SourcesResponse.class);
  103. if (null == hrgResponse || hrgResponse.getResultCode() == -1) {
  104. sourceArray[i] = 0;
  105. continue;
  106. }
  107. for (Map<String, Object> item : hrgResponse.getData()) {
  108. if ((int) item.get("leftNum") > 0) {
  109. sourceArray[i] = 1;
  110. break;
  111. }
  112. }
  113. }
  114. return ResultVoUtil.success(sourceArray);
  115. }
  116. public ResultVo<Object> getDoctorSources(GetDoctorSourcesParam param) {
  117. String url = String.format(hrgApiUrl + "/getDoctorByDateAndDept?requestDay=%s&unitCode=%s", param.getDate(), param.getDeptCode());
  118. RestTemplate template = new RestTemplate();
  119. SourcesResponse data = template.getForObject(url, SourcesResponse.class);
  120. if (null == data || null == data.getResultCode()) {
  121. return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
  122. }
  123. if (data.getResultCode() == -1) {
  124. return ResultVoUtil.fail(ExceptionEnum.SLIGHTLY_ERROR, data.getResultMessage());
  125. }
  126. data.getData().removeIf(map -> (int) map.get("leftNum") == 0);
  127. if (data.getData().size() == 0) {
  128. return ResultVoUtil.fail(ExceptionEnum.SLIGHTLY_ERROR);
  129. }
  130. for (Map<String, Object> map : data.getData()) {
  131. DoctorInfo info = dao.selectPortraitAndIntroduction(map.get("doctorCode").toString());
  132. if (null != info) {
  133. map.put("portrait", info.getPortrait());
  134. map.put("introduction", info.getIntroduction());
  135. }
  136. }
  137. data.getData().sort((o1, o2) -> {
  138. Integer i1 = Integer.parseInt(o1.get("empTitCode").toString());
  139. Integer i2 = Integer.parseInt(o2.get("empTitCode").toString());
  140. int diff = i1 - i2;
  141. return Integer.compare(diff, 0);
  142. });
  143. return ResultVoUtil.success(data.getData());
  144. }
  145. public ResultVo<Object> getDoctorArrangement(GetDoctorSourcesParam param) {
  146. String url = String.format(hrgApiUrl + "/getRequestByDateAndDeptAndDoctor?requestDay=%s&unitCode=%s&doctorCode=%s",
  147. param.getDate(), param.getDeptCode(), param.getDoctorCode());
  148. RestTemplate template = new RestTemplate();
  149. SourcesResponse data = template.getForObject(url, SourcesResponse.class);
  150. if (null == data || null == data.getResultCode()) {
  151. return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
  152. }
  153. if (data.getResultCode() == -1) {
  154. return ResultVoUtil.fail(ExceptionEnum.SLIGHTLY_ERROR, data.getResultMessage());
  155. }
  156. data.getData().removeIf(map -> (int) map.get("leftNum") == 0);
  157. if (data.getData().size() == 0) {
  158. return ResultVoUtil.fail(ExceptionEnum.SLIGHTLY_ERROR);
  159. }
  160. return ResultVoUtil.success(data.getData());
  161. }
  162. public ResultVo<Integer[]> getSourcesByDateAndDoctor(GetDoctorSourcesParam param) {
  163. Integer[] source = new Integer[7];
  164. source[0] = getDoctorArrangement(param).getCode();
  165. Calendar calendar = Calendar.getInstance();
  166. SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
  167. for (int i = 1; i < source.length; i++) {
  168. calendar.add(Calendar.DATE, 1);
  169. param.setDate(dateFormat.format(calendar.getTime()));
  170. source[i] = getDoctorArrangement(param).getCode();
  171. }
  172. return ResultVoUtil.success(source);
  173. }
  174. public ResultVo<Map<String, Object>> getGhFee(GetGhFeeParam param) {
  175. String url = String.format(hrgApiUrl + "/getMzChargeTypeByRequestIdForHaiCi?mzyRequestId=%d&patientId=%s",
  176. param.getMzyRequestId(), param.getPatientId());
  177. RestTemplate template = new RestTemplate();
  178. HrgCommonResponse data = template.getForObject(url, HrgCommonResponse.class);
  179. log.info("获取挂号费用:\n参数:{},\n结果:{}", param, data);
  180. if (null == data) {
  181. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "网络服务错误!");
  182. }
  183. if (-1 == data.getCode()) {
  184. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, data.getMessage());
  185. }
  186. Map<String, Object> map = new HashMap<>(Constants.Capacity.TWO);
  187. map.put("fee", data.getData());
  188. map.put("message", data.getMessage());
  189. return ResultVoUtil.success(map);
  190. }
  191. public ResultVo<DoctorInfo> getDoctorInfo(String doctorCode, String openId) {
  192. DoctorInfo doctor = dao.selectDoctorInfo(doctorCode, openId);
  193. if (null == doctor) {
  194. return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "未找到医生信息!");
  195. }
  196. return ResultVoUtil.success(doctor);
  197. }
  198. public ResultVo<String> checkAppointmentRequirements(String patientId, String deptCode) {
  199. String idCard = dao.selectPatientIdCard(patientId);
  200. if (!IdCardUtil.isValidatedIdCard(idCard)) {
  201. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "您在我院绑定的身份证号不是有效的身份证号," +
  202. "请前往【个人中心 - 我的就诊人 - 就诊人信息】进行修改。");
  203. }
  204. String mzClass = dao.selectMzClass(deptCode);
  205. if (Constants.MzClass.GYNAECOLOGY.equals(mzClass)) {
  206. if (IdCardUtil.getGenderByIdCard(idCard) == Gender.MALE) {
  207. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "男性无法在妇产科挂号,请选择其他科室。");
  208. }
  209. }
  210. if (Constants.MzDept.PEDIATRICS.equals(deptCode)) {
  211. if (IdCardUtil.getAgeByIdCard(idCard) >= 18) {
  212. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "成年人无法在儿科挂号,请选择其他科室。");
  213. }
  214. }
  215. return ResultVoUtil.success();
  216. }
  217. public ResultVo<String> getDoctorQrCode(String doctorCode) {
  218. final String qywxToken = PropertiesUtil.getLocalProperty("qywxToken");
  219. final String userid = redis.getEmployeeCodeRs(doctorCode);
  220. final String url = String.format("https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=%s&userid=%s", qywxToken, userid);
  221. RestTemplate restTemplate = new RestTemplate();
  222. final String result = restTemplate.getForObject(url, String.class);
  223. JSONObject json = JSONObject.parseObject(result);
  224. return ResultVoUtil.success(json.getString("qr_code"));
  225. }
  226. public ResultVo<List<Map<String, String>>> getPaidMzGhList(String patientId) {
  227. log.info("获取门诊挂号记录列表:{}", patientId);
  228. healthCardService.reportHisData(patientId, "01010111", null, null);
  229. RestTemplate template = new RestTemplate();
  230. JSONObject params = new JSONObject();
  231. params.put("patientId", patientId);
  232. SourcesResponse hrgResponse = template.postForObject(hrgApiUrl + "/getRegistrationForPaid", params, SourcesResponse.class);
  233. return ThmzUtil.getResultVoCompletableFuture(hrgResponse);
  234. }
  235. public ResultVo<List<MzyReqrec>> listMzyReqrec(BriefPatInfo patInfo) {
  236. String url = hrgApiUrl + "/listMzyReqrec?patientId=" + patInfo.getPatientId() + "&payMark=" + patInfo.getPayMark();
  237. JSONObject response = new RestTemplate().getForObject(url, JSONObject.class);
  238. if (null == response) {
  239. return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
  240. }
  241. Integer resultCode = response.getInteger("resultCode");
  242. if (null == resultCode) {
  243. return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
  244. }
  245. if (resultCode != 0) {
  246. return ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, response.getString("message"));
  247. }
  248. JSONArray data = response.getJSONArray("data");
  249. if (null == data || data.size() == 0) {
  250. return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
  251. }
  252. List<MzyReqrec> list = new ArrayList<>();
  253. for (int i = 0; i < data.size(); i++) {
  254. JSONObject mzy = data.getJSONObject(i).getJSONObject("mzyReqrec");
  255. if (null != mzy) {
  256. list.add(JSONObject.parseObject(JSONObject.toJSONString(mzy), MzyReqrec.class));
  257. }
  258. }
  259. if (list.isEmpty()) {
  260. return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
  261. }
  262. return ResultVoUtil.success(list);
  263. }
  264. public ResultVo<MzyReqrec> getMzyReqrecInfo(BriefPatInfo patInfo) {
  265. String url = hrgApiUrl + "/getMzyReqrecInfo?patientId=" + patInfo.getPatientId() + "&times=" + patInfo.getTimes();
  266. JSONObject response = new RestTemplate().getForObject(url, JSONObject.class);
  267. if (null == response) {
  268. return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
  269. }
  270. Integer resultCode = response.getInteger("resultCode");
  271. if (null == resultCode) {
  272. return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
  273. }
  274. if (resultCode != 0) {
  275. return ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, response.getString("message"));
  276. }
  277. JSONObject data = response.getJSONObject("data");
  278. if (null == data) {
  279. return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
  280. }
  281. MzyReqrec mzyReqrec = JSONObject.parseObject(JSONObject.toJSONString(data), MzyReqrec.class);
  282. if (patInfo.filterUnpaidReq() && StringUtil.notBlank(mzyReqrec.getPaymode())) {
  283. return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
  284. }
  285. mzyReqrec.setDoctorCode(redis.getEmployeeName(mzyReqrec.getDoctorCode()));
  286. mzyReqrec.setUnitCode(redis.getDepartmentName(mzyReqrec.getUnitCode()));
  287. mzyReqrec.setAmpm(redis.getAmpmName(mzyReqrec.getAmpm()));
  288. return ResultVoUtil.success(mzyReqrec);
  289. }
  290. public ResultVo<String> cancelReqrec(MzyReqrec mzyReq) {
  291. if (invalidCancelReqrec(mzyReq)) {
  292. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "仅支持最近15天内尚未就诊的微信自助挂号。");
  293. }
  294. String url = hrgApiUrl + "/cancelReqrec";
  295. JSONObject params = new JSONObject();
  296. params.put("patientId", mzyReq.getPatientId());
  297. params.put("times", mzyReq.getTimes());
  298. JSONObject response = new RestTemplate().postForObject(url, params, JSONObject.class);
  299. log.info("自助退号:参数:{};结果:{}", params, response);
  300. if (null == response) {
  301. return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
  302. }
  303. Integer rescode = response.getInteger("code");
  304. if (null == rescode) {
  305. return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
  306. }
  307. if (rescode != 0) {
  308. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, response.getString("message"));
  309. }
  310. return wxRefundService.autoRefund(mzyReq.getPsordnum(), "自助退号。");
  311. }
  312. private boolean invalidCancelReqrec(MzyReqrec mzyReq) {
  313. return DateUtil.dateDiff(mzyReq.getRequestDayStr()) > 15 || null == mzyReq.getPaymode()
  314. || mzyReq.getVisitedMark().equals("1") || mzyReq.getCancelMark().equals("1");
  315. }
  316. }