package thyyxxk.wxservice_server.service; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import thyyxxk.wxservice_server.config.exception.ExceptionEnum; import thyyxxk.wxservice_server.constant.Constants; import thyyxxk.wxservice_server.constant.Gender; import thyyxxk.wxservice_server.dao.AppointmentDao; import thyyxxk.wxservice_server.entity.BriefPatInfo; import thyyxxk.wxservice_server.entity.ResultVo; import thyyxxk.wxservice_server.entity.appointment.*; import thyyxxk.wxservice_server.entity.hrgresponse.SourcesResponse; import thyyxxk.wxservice_server.entity.hrgresponse.HrgCommonResponse; import thyyxxk.wxservice_server.entity.hrgresponse.MzClassResponse; import thyyxxk.wxservice_server.utils.*; import java.text.SimpleDateFormat; import java.util.*; /** * @author dj */ @Slf4j @Service public class AppointmentService { private static final List mzClasses = new ArrayList<>(); private final AppointmentDao dao; private final RedisLikeService redis; private final ElectronicHealthCardService healthCardService; private final WxRefundService wxRefundService; @Value("${hrgApiUrl}") private String hrgApiUrl; @Autowired public AppointmentService(AppointmentDao dao, RedisLikeService redis, ElectronicHealthCardService healthCardService, WxRefundService wxRefundService) { this.dao = dao; this.redis = redis; this.healthCardService = healthCardService; this.wxRefundService = wxRefundService; } public ResultVo> getAllDepartments() { if (ListUtil.notEmpty(mzClasses)) { return ResultVoUtil.success(mzClasses); } log.info("重新获取门诊科室并缓存。"); List> tempMzClasses = fetchMzClassesFromApi(); if (null == tempMzClasses) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "获取科室分类失败,请联系服务中心。"); } for (Map mzClass : tempMzClasses) { fetchMzDepartmentsByMzClasses(mzClass); } return ResultVoUtil.success(mzClasses); } private List> fetchMzClassesFromApi() { RestTemplate template = new RestTemplate(); MzClassResponse response = template.getForObject(hrgApiUrl + "/getMzClass", MzClassResponse.class); if (null == response || -1 == response.getResultCode()) { return null; } return response.getData(); } private void fetchMzDepartmentsByMzClasses(Map mzClass) { String mzClassCode = mzClass.get("code").toString(); JSONObject params = JSONObject.parseObject("{\"mzClass\": \"" + mzClassCode + "\"}"); MzClassResponse tempMzDepartments = new RestTemplate().postForObject(hrgApiUrl + "/getUnitCodeByMzClass", params, MzClassResponse.class); if (null != tempMzDepartments && tempMzDepartments.getResultCode() == 0) { List children = new ArrayList<>(); for (Map child : tempMzDepartments.getData()) { MzDept childDepartment = new MzDept(child.get("code").toString(), child.get("name").toString()); List> grandChildrenMap = CastUtil.cast(child.get("children")); if (null != grandChildrenMap && grandChildrenMap.size() > 0) { List grandChildren = new ArrayList<>(); for (Map grandChild : grandChildrenMap) { grandChildren.add(new MzDept(grandChild.get("code").toString(), grandChild.get("name").toString())); } childDepartment.setChildren(grandChildren); } children.add(childDepartment); } mzClasses.add(new MzClass(mzClassCode, mzClass.get("name").toString(), children)); } } public ResultVo refreshMzClasses() { mzClasses.clear(); log.info("门诊科室缓存已重置。"); return ResultVoUtil.success("门诊科室缓存已重置。"); } public ResultVo getSourcesByDate(GetSourcesByDateParam param) { Integer[] sourceArray = new Integer[7]; RestTemplate template = new RestTemplate(); Calendar calendar = Calendar.getInstance(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); for (int i = 0; i < 7; i++) { sourceArray[i] = 0; int addNum = i == 0 ? 0 : 1; calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) + addNum); String date = format.format(calendar.getTime()); String url = String.format(hrgApiUrl + "/getDoctorByDateAndDept?requestDay=%s&unitCode=%s", date, param.getDept()); SourcesResponse hrgResponse = template.getForObject(url, SourcesResponse.class); if (null == hrgResponse || hrgResponse.getResultCode() == -1) { sourceArray[i] = 0; continue; } for (Map item : hrgResponse.getData()) { if ((int) item.get("leftNum") > 0) { sourceArray[i] = 1; break; } } } return ResultVoUtil.success(sourceArray); } public ResultVo getDoctorSources(GetDoctorSourcesParam param) { String url = String.format(hrgApiUrl + "/getDoctorByDateAndDept?requestDay=%s&unitCode=%s", param.getDate(), param.getDeptCode()); RestTemplate template = new RestTemplate(); SourcesResponse data = template.getForObject(url, SourcesResponse.class); if (null == data || null == data.getResultCode()) { return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR); } if (data.getResultCode() == -1) { return ResultVoUtil.fail(ExceptionEnum.SLIGHTLY_ERROR, data.getResultMessage()); } data.getData().removeIf(map -> (int) map.get("leftNum") == 0); if (data.getData().size() == 0) { return ResultVoUtil.fail(ExceptionEnum.SLIGHTLY_ERROR); } for (Map map : data.getData()) { DoctorInfo info = dao.selectPortraitAndIntroduction(map.get("doctorCode").toString()); if (null != info) { map.put("portrait", info.getPortrait()); map.put("introduction", info.getIntroduction()); } } data.getData().sort((o1, o2) -> { Integer i1 = Integer.parseInt(o1.get("empTitCode").toString()); Integer i2 = Integer.parseInt(o2.get("empTitCode").toString()); int diff = i1 - i2; return Integer.compare(diff, 0); }); return ResultVoUtil.success(data.getData()); } public ResultVo getDoctorArrangement(GetDoctorSourcesParam param) { String url = String.format(hrgApiUrl + "/getRequestByDateAndDeptAndDoctor?requestDay=%s&unitCode=%s&doctorCode=%s", param.getDate(), param.getDeptCode(), param.getDoctorCode()); RestTemplate template = new RestTemplate(); SourcesResponse data = template.getForObject(url, SourcesResponse.class); if (null == data || null == data.getResultCode()) { return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR); } if (data.getResultCode() == -1) { return ResultVoUtil.fail(ExceptionEnum.SLIGHTLY_ERROR, data.getResultMessage()); } data.getData().removeIf(map -> (int) map.get("leftNum") == 0); if (data.getData().size() == 0) { return ResultVoUtil.fail(ExceptionEnum.SLIGHTLY_ERROR); } return ResultVoUtil.success(data.getData()); } public ResultVo getSourcesByDateAndDoctor(GetDoctorSourcesParam param) { Integer[] source = new Integer[7]; source[0] = getDoctorArrangement(param).getCode(); Calendar calendar = Calendar.getInstance(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); for (int i = 1; i < source.length; i++) { calendar.add(Calendar.DATE, 1); param.setDate(dateFormat.format(calendar.getTime())); source[i] = getDoctorArrangement(param).getCode(); } return ResultVoUtil.success(source); } public ResultVo> getGhFee(GetGhFeeParam param) { String url = String.format(hrgApiUrl + "/getMzChargeTypeByRequestIdForHaiCi?mzyRequestId=%d&patientId=%s", param.getMzyRequestId(), param.getPatientId()); RestTemplate template = new RestTemplate(); HrgCommonResponse data = template.getForObject(url, HrgCommonResponse.class); log.info("获取挂号费用:\n参数:{},\n结果:{}", param, data); if (null == data) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "网络服务错误!"); } if (-1 == data.getCode()) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, data.getMessage()); } Map map = new HashMap<>(Constants.Capacity.TWO); map.put("fee", data.getData()); map.put("message", data.getMessage()); return ResultVoUtil.success(map); } public ResultVo getDoctorInfo(String doctorCode, String openId) { DoctorInfo doctor = dao.selectDoctorInfo(doctorCode, openId); if (null == doctor) { return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "未找到医生信息!"); } return ResultVoUtil.success(doctor); } public ResultVo checkAppointmentRequirements(String patientId, String deptCode) { String idCard = dao.selectPatientIdCard(patientId); if (!IdCardUtil.isValidatedIdCard(idCard)) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "您在我院绑定的身份证号不是有效的身份证号," + "请前往【个人中心 - 我的就诊人 - 就诊人信息】进行修改。"); } String mzClass = dao.selectMzClass(deptCode); if (Constants.MzClass.GYNAECOLOGY.equals(mzClass)) { if (IdCardUtil.getGenderByIdCard(idCard) == Gender.MALE) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "男性无法在妇产科挂号,请选择其他科室。"); } } if (Constants.MzDept.PEDIATRICS.equals(deptCode)) { if (IdCardUtil.getAgeByIdCard(idCard) >= 18) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "成年人无法在儿科挂号,请选择其他科室。"); } } return ResultVoUtil.success(); } public ResultVo getDoctorQrCode(String doctorCode) { final String qywxToken = PropertiesUtil.getLocalProperty("qywxToken"); final String userid = redis.getEmployeeCodeRs(doctorCode); final String url = String.format("https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=%s&userid=%s", qywxToken, userid); RestTemplate restTemplate = new RestTemplate(); final String result = restTemplate.getForObject(url, String.class); JSONObject json = JSONObject.parseObject(result); return ResultVoUtil.success(json.getString("qr_code")); } public ResultVo>> getPaidMzGhList(String patientId) { log.info("获取门诊挂号记录列表:{}", patientId); healthCardService.reportHisData(patientId, "01010111", null, null); RestTemplate template = new RestTemplate(); JSONObject params = new JSONObject(); params.put("patientId", patientId); SourcesResponse hrgResponse = template.postForObject(hrgApiUrl + "/getRegistrationForPaid", params, SourcesResponse.class); return ThmzUtil.getResultVoCompletableFuture(hrgResponse); } public ResultVo> listMzyReqrec(BriefPatInfo patInfo) { String url = hrgApiUrl + "/listMzyReqrec?patientId=" + patInfo.getPatientId() + "&payMark=" + patInfo.getPayMark(); JSONObject response = new RestTemplate().getForObject(url, JSONObject.class); if (null == response) { return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR); } Integer resultCode = response.getInteger("resultCode"); if (null == resultCode) { return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR); } if (resultCode != 0) { return ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, response.getString("message")); } JSONArray data = response.getJSONArray("data"); if (null == data || data.size() == 0) { return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST); } List list = new ArrayList<>(); for (int i = 0; i < data.size(); i++) { JSONObject mzy = data.getJSONObject(i).getJSONObject("mzyReqrec"); if (null != mzy) { list.add(JSONObject.parseObject(JSONObject.toJSONString(mzy), MzyReqrec.class)); } } if (list.isEmpty()) { return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST); } return ResultVoUtil.success(list); } public ResultVo getMzyReqrecInfo(BriefPatInfo patInfo) { String url = hrgApiUrl + "/getMzyReqrecInfo?patientId=" + patInfo.getPatientId() + "×=" + patInfo.getTimes(); JSONObject response = new RestTemplate().getForObject(url, JSONObject.class); if (null == response) { return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR); } Integer resultCode = response.getInteger("resultCode"); if (null == resultCode) { return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR); } if (resultCode != 0) { return ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, response.getString("message")); } JSONObject data = response.getJSONObject("data"); if (null == data) { return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST); } MzyReqrec mzyReqrec = JSONObject.parseObject(JSONObject.toJSONString(data), MzyReqrec.class); if (patInfo.filterUnpaidReq() && StringUtil.notBlank(mzyReqrec.getPaymode())) { return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST); } mzyReqrec.setDoctorCode(redis.getEmployeeName(mzyReqrec.getDoctorCode())); mzyReqrec.setUnitCode(redis.getDepartmentName(mzyReqrec.getUnitCode())); mzyReqrec.setAmpm(redis.getAmpmName(mzyReqrec.getAmpm())); return ResultVoUtil.success(mzyReqrec); } public ResultVo cancelReqrec(MzyReqrec mzyReq) { if (invalidCancelReqrec(mzyReq)) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "仅支持最近15天内尚未就诊的微信自助挂号。"); } String url = hrgApiUrl + "/cancelReqrec"; JSONObject params = new JSONObject(); params.put("patientId", mzyReq.getPatientId()); params.put("times", mzyReq.getTimes()); JSONObject response = new RestTemplate().postForObject(url, params, JSONObject.class); log.info("自助退号:参数:{};结果:{}", params, response); if (null == response) { return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR); } Integer rescode = response.getInteger("code"); if (null == rescode) { return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR); } if (rescode != 0) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, response.getString("message")); } return wxRefundService.autoRefund(mzyReq.getPsordnum(), "自助退号。"); } private boolean invalidCancelReqrec(MzyReqrec mzyReq) { return DateUtil.dateDiff(mzyReq.getRequestDayStr()) > 15 || null == mzyReq.getPaymode() || mzyReq.getVisitedMark().equals("1") || mzyReq.getCancelMark().equals("1"); } }