package thyyxxk.wxservice_server.service; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; 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.factory.thmz.ThmzService; import thyyxxk.wxservice_server.factory.thmz.model.QueryMzDoctorRequest; import thyyxxk.wxservice_server.factory.thmz.model.QueryMzyReqrecRequest; import thyyxxk.wxservice_server.factory.thmz.model.QueryRegisterCostRequest; import thyyxxk.wxservice_server.factory.thmz.model.QueryUnitCodeRequest; import thyyxxk.wxservice_server.utils.*; import java.text.SimpleDateFormat; import java.util.*; /** * @author dj */ @Slf4j @Service public class AppointmentService { private static final Boolean NORMAL_CLASSES = Boolean.FALSE; private static final Boolean NIGHT_CLASSES = Boolean.TRUE; private static final List mzClasses = new ArrayList<>(); private static final List nightMzClasses = new ArrayList<>(); private final AppointmentDao dao; private final RedisLikeService redis; private final ElectronicHealthCardService healthCardService; private final WxRefundService wxRefundService; private final ThmzService thmzService; private static final int[] ampmValue = new int[]{830, 900, 930, 1000, 1030, 1100, 1130, 1200, 1430, 1500, 1530, 1600, 1630, 1700, 1730}; private static final String[] ampmLabel = new String[]{"a1","a2","a3","a4","a5","a6","a7","a8","p1","p2","p3","p4","p5","p6","p7"}; @Autowired public AppointmentService(AppointmentDao dao, RedisLikeService redis, ElectronicHealthCardService healthCardService, WxRefundService wxRefundService, ThmzService thmzService) { this.dao = dao; this.redis = redis; this.healthCardService = healthCardService; this.wxRefundService = wxRefundService; this.thmzService = thmzService; } public ResultVo> getAllDepartments() { if (ListUtil.notEmpty(mzClasses)) { return ResultVoUtil.success(mzClasses); } log.info("重新获取门诊科室并缓存。"); ResultVo>> mzClassResponse = thmzService.getMzClass(); if (mzClassResponse.getCode() != ExceptionEnum.SUCCESS.getCode()) { return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR, mzClassResponse.getMessage()); } List> tempMzClasses = mzClassResponse.getData(); tempMzClasses.sort(Comparator.comparing(obj -> (int) obj.get("sortCode"))); String[] dateRange = new String[]{null, null}; for (Map mzClass : tempMzClasses) { fetchMzDepartmentsByMzClasses(mzClass, NORMAL_CLASSES, dateRange); } return ResultVoUtil.success(mzClasses); } public ResultVo> getAllNightDepartments() { if (ListUtil.notEmpty(nightMzClasses)) { return ResultVoUtil.success(nightMzClasses); } log.info("重新获取夜间门诊科室并缓存。"); ResultVo>> mzClassResponse = thmzService.getMzClass(); if (mzClassResponse.getCode() != ExceptionEnum.SUCCESS.getCode()) { return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR, mzClassResponse.getMessage()); } List> tempMzClasses = mzClassResponse.getData(); tempMzClasses.sort(Comparator.comparing(obj -> (int) obj.get("sortCode"))); String[] oneWeekOffset = DateUtil.getOneWeekOffset(); for (Map mzClass : tempMzClasses) { fetchMzDepartmentsByMzClasses(mzClass, NIGHT_CLASSES, oneWeekOffset); } return ResultVoUtil.success(nightMzClasses); } private void fetchMzDepartmentsByMzClasses(Map mzClass, boolean nightClinic, String[] dateRange) { String mzClassCode = mzClass.get("code").toString(); QueryUnitCodeRequest request = new QueryUnitCodeRequest.Builder() .mzClass(mzClassCode).p4Request(nightClinic) .beginTime(dateRange[0]).endTime(dateRange[1]).build(); ResultVo>> queryUnitCodeResponse = thmzService.getUnitCodeByMzClass(request); if (queryUnitCodeResponse.getCode() == ExceptionEnum.SUCCESS.getCode()) { List> mzDepartments = queryUnitCodeResponse.getData(); List departmentList = new ArrayList<>(); for (Map tempDepartment : mzDepartments) { String sortCode = (String) tempDepartment.get("sortCode"); if (!StringUtil.isDigit(sortCode)) { sortCode = "9999"; } MzDept department = new MzDept(tempDepartment.get("code").toString(), tempDepartment.get("name").toString(), Integer.parseInt(sortCode)); List> tempChildren = CastUtil.cast(tempDepartment.get("children")); if (ListUtil.notEmpty(tempChildren)) { List children = new ArrayList<>(); for (Map tempChild : tempChildren) { String childSortCode = (String) tempChild.get("sortCode"); if (!StringUtil.isDigit(childSortCode)) { childSortCode = "9999"; } children.add(new MzDept(tempChild.get("code").toString(), tempChild.get("name").toString(), Integer.parseInt(childSortCode))); } children.sort(Comparator.comparing(MzDept::getSortNo)); department.setChildren(children); } departmentList.add(department); } if (departmentList.isEmpty()) { return; } departmentList.sort(Comparator.comparing(MzDept::getSortNo)); if (nightClinic) { nightMzClasses.add(new MzClass(mzClassCode, mzClass.get("name").toString(), departmentList)); } else { mzClasses.add(new MzClass(mzClassCode, mzClass.get("name").toString(), departmentList)); } } } public ResultVo refreshMzClasses() { mzClasses.clear(); log.info("门诊科室缓存已重置。"); return ResultVoUtil.success("门诊科室缓存已重置。"); } public ResultVo refreshNightMzClasses() { nightMzClasses.clear(); log.info("夜间门诊科室缓存已重置。"); return ResultVoUtil.success("夜间门诊科室缓存已重置。"); } public ResultVo> getSourcesByDate(GetSourcesByDateParam param) { Integer[] sourceArray = new Integer[7]; 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()); QueryMzDoctorRequest request = new QueryMzDoctorRequest.Builder() .requestDay(date).unitCode(param.getDept()).build(); ResultVo>> queryMzDoctorResponse = thmzService.getDoctorByDateAndDept(request); if (queryMzDoctorResponse.getCode() != ExceptionEnum.SUCCESS.getCode()) { sourceArray[i] = 0; continue; } for (Map item : queryMzDoctorResponse.getData()) { if (!param.getNightClinic() || (Boolean) item.get("isP4Request")) { sourceArray[i] = 1; break; } } } Map resultMap = new HashMap<>(); resultMap.put("description", dao.selectDeptDescription(param.getDept())); resultMap.put("sources", sourceArray); return ResultVoUtil.success(resultMap); } public ResultVo>> getDoctorSources(GetDoctorSourcesParam param) { QueryMzDoctorRequest request = new QueryMzDoctorRequest.Builder() .requestDay(param.getDate()).unitCode(param.getDeptCode()).build(); ResultVo>> response = thmzService.getDoctorByDateAndDept(request); if (response.getCode() != ExceptionEnum.SUCCESS.getCode()) { return response; } if (param.getNightClinic()) { response.getData().removeIf(map -> !((Boolean) map.get("isP4Request"))); } for (Map map : response.getData()) { DoctorInfo info = dao.selectPortraitAndIntroduction(map.get("doctorCode").toString()); if (null != info) { map.put("portrait", info.getPortrait()); map.put("introduction", info.getIntroduction()); } } response.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 response; } public ResultVo>> getDoctorArrangement(GetDoctorSourcesParam param) { QueryMzDoctorRequest request = new QueryMzDoctorRequest.Builder() .requestDay(param.getDate()).unitCode(param.getDeptCode()) .doctorCode(param.getDoctorCode()).build(); ResultVo>> response = thmzService.getDoctorsArrangement(request); if (response.getCode() != ExceptionEnum.SUCCESS.getCode()) { return response; } String today = DateUtil.formatDatetime(new Date(), "yyyy-MM-dd"); if (param.getNeedExcludePassedTime() && param.getDate().equals(today)) { int currentHourMinute = DateUtil.parseHourMinuteToInteger(); int validAmpmIndex = 0; for (int i = 0; i < ampmValue.length; i++) { if (currentHourMinute < ampmValue[i]) { validAmpmIndex = i; break; } } for (Map map : response.getData()) { for (int i = 0; i < validAmpmIndex; i++) { map.remove(ampmLabel[i]); } } } if (response.getData().isEmpty()) { return ResultVoUtil.fail(ExceptionEnum.SLIGHTLY_ERROR); } return response; } 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) { QueryRegisterCostRequest request = new QueryRegisterCostRequest.Builder() .mzyRequestId(param.getMzyRequestId()) .patientId(param.getPatientId()).build(); return thmzService.getRegisterCost(request); } 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.isPediatrics(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) { healthCardService.reportHisData(patientId, "01010111", null, null); return thmzService.getPaidMzGhList(patientId); } public ResultVo> listMzyReqrec(BriefPatInfo patInfo) { QueryMzyReqrecRequest request = new QueryMzyReqrecRequest.Builder() .patientId(patInfo.getPatientId()).payMark(patInfo.getPayMark()).build(); return thmzService.listMzyReqrec(request); } public ResultVo getMzyReqrecInfo(BriefPatInfo patInfo) { QueryMzyReqrecRequest request = new QueryMzyReqrecRequest.Builder() .patientId(patInfo.getPatientId()).times(patInfo.getTimes()) .onlyShowUnpaid(patInfo.filterUnpaidReq()).build(); return thmzService.getMzyReqrecInfo(request); } public ResultVo cancelReqrec(MzyReqrec mzyReq) { ResultVo cancelReqResponse = cancelReqFromHis(mzyReq); if (cancelReqResponse.getCode() == ExceptionEnum.SUCCESS.getCode()) { return wxRefundService.autoRefund(mzyReq.getPsordnum(), "自助退号。"); } return cancelReqResponse; } public ResultVo cancelReqFromHis(MzyReqrec mzyReq) { if (invalidCancelReqrec(mzyReq)) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "仅支持最近15天内尚未就诊的微信自助挂号。"); } QueryMzyReqrecRequest request = new QueryMzyReqrecRequest.Builder() .patientId(mzyReq.getPatientId()).times(mzyReq.getTimes()).build(); return thmzService.cancelReqFromHis(request); } private boolean invalidCancelReqrec(MzyReqrec mzyReq) { return !ThmzUtil.validRefundTime(new Date(), mzyReq.getRequestDayStr()) || null == mzyReq.getPaymode() || mzyReq.getVisitedMark().equals("1") || mzyReq.getCancelMark().equals("1"); } }