fhx
2024-10-10 6623d16a2e4de709a64d4980ff8b5cc4fb6269d5
Merge remote-tracking branch 'origin/fhx-base-医助需求1008' into master-test

# Conflicts:
# phi_platform_user/src/main/java/com/hx/phip/controller/appointment/AppAutoMateController.java
# phi_platform_user/src/main/java/com/hx/phip/controller/appointment/AppointmentController.java
# phi_platform_user/src/main/java/com/hx/phip/service/appointment/AppointmentV2Service.java
# phi_platform_user/src/main/java/com/hx/phip/service/appointment/impl/AppointmentV2ServiceImpl.java
1个文件已添加
7个文件已修改
1168 ■■■■■ 已修改文件
phi_platform_user/src/main/java/com/hx/phip/controller/appointment/AppAutoMateController.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
phi_platform_user/src/main/java/com/hx/phip/controller/appointment/AppointmentController.java 517 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
phi_platform_user/src/main/java/com/hx/phip/controller/appointment/CrmSelfV2Controller.java 438 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
phi_platform_user/src/main/java/com/hx/phip/controller/meiji/MeiJiDataController.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
phi_platform_user/src/main/java/com/hx/phip/controller/micro/MicroRecordController.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
phi_platform_user/src/main/java/com/hx/phip/controller/micro/MicroRecordV2Controller.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
phi_platform_user/src/main/java/com/hx/phip/service/appointment/AppointmentV2Service.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
phi_platform_user/src/main/java/com/hx/phip/service/appointment/impl/AppointmentV2ServiceImpl.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
phi_platform_user/src/main/java/com/hx/phip/controller/appointment/AppAutoMateController.java
@@ -11,7 +11,6 @@
import com.hx.phiappt.constants.tool.appointment.autoMate.AppAutoMateHandleUtil;
import com.hx.phiappt.constants.tool.appointment.autoMate.AppAutoMateV5Util;
import com.hx.phiappt.dao.mapper.*;
import com.hx.phiappt.dto.appointment.AppointmentDto;
import com.hx.phiappt.model.*;
import com.hx.phiappt.vo.ApponintmentVo;
import com.hx.phiappt.vo.ProjectVo;
@@ -57,16 +56,16 @@
        }
        if(StringUtils.isEmpty(dto.getShopId())) {
            throwParamException("请选择门店");
            throw new TipsException("请选择门店");
        }
        Shop shop = commonService.selectOneByKey(ShopMapper.class, dto.getShopId());
        if(shop == null) {
            throwParamException("找不到门店");
            throw new TipsException("找不到门店");
        }
        if(StringUtils.isEmpty(dto.getUserId())) {
            throwParamException("请选择用户");
            throw new TipsException("请选择用户");
        }
        Map<String, Object> values = new HashMap<>();
@@ -79,7 +78,7 @@
        User user = commonService.selectOne(UserMapper.class, sqlSentence);
        if(user == null) {
            throwParamException("找不到用户");
            throw new TipsException("找不到用户");
        }
        Employee doctor = null;
@@ -96,22 +95,22 @@
            doctor = commonService.selectOne(EmployeeMapper.class, sqlSentence);
            if(doctor == null)
            {
                throwParamException("找不到医生");
                throw new TipsException("找不到医生");
            }
        }else{
            doctorId = null;
        }
        if(StringUtils.isEmpty(dto.getArriveDate(), dto.getStartTime())) {
            throwParamException("请选择到店日期和时间");
            throw new TipsException("请选择到店日期和时间");
        }
        if(dto.getVisitType() == null) {
            throwParamException("请选择就诊类型");
            throw new TipsException("请选择就诊类型");
        }
        if(dto.getAppType() == null) {
            throwParamException("请选择预约类型");
            throw new TipsException("请选择预约类型");
        }
        Integer waitDuration = dto.getWaitDuration();
@@ -141,6 +140,11 @@
            dto.setRealMzTime(0);
        }
        //推荐匹配数量为空,则默认2
        if(dto.getMateNum() == null){
            dto.setMateNum(2);
        }
        //术前时间
        int sqTime = 0;
@@ -155,11 +159,13 @@
        //是否再生项目
        String zsProjectId = "";
        boolean isZsP = false;
        //是否有非生美项目
        boolean isNotSm = false;
        //复查可以不选项目
        if(StringUtils.isEmpty(dto.getProjectJson()) && dto.getAppType() != Appointment.APP_TYPE_REVIEW)
        {
            throwParamException("请选择项目");
            throw new TipsException("请选择项目");
        }else {
            //再生项目逻辑,目前写死一个项目
@@ -184,12 +190,12 @@
                num = temp.getIntValue("num");
                if(StringUtils.isEmpty(id) || num <= 0)
                {
                    throwParamException("请选择正确项目和数量");
                    throw new TipsException("请选择正确项目和数量");
                }
                p = commonService.selectOneByKey(ProjectMapper.class, id);
                if(p == null || p.getIsDel().equals(BaseEntity.YES)  || p.getIsUp().equals(BaseEntity.NO))
                {
                    throwParamException("找不到项目或者项目下架");
                    throw new TipsException("找不到项目或者项目下架");
                }
                projectList.add(p);
@@ -208,9 +214,13 @@
                    isDevice++;
                }
                if(!isNotSm && p.getIsLifeBeauty().equals(BaseEntity.NO)){
                    isNotSm = true;
                }
                if(zsProjectId.equals(id)){
                    if(num > 1){
                        throwParamException("再生项目数量不能大于1!");
                        throw new TipsException("再生项目数量不能大于1!");
                    }
                    isZsP = true;
                }
@@ -219,7 +229,11 @@
        //判断如果包含了再生项目,
        if(isZsP && projectList.size() > 1){
            throwParamException("预约项目里面有再生项目,不能和其他项目同时预约!");
            throw new TipsException("预约项目里面有再生项目,不能和其他项目同时预约!");
        }
        if(isNotSm && StringUtils.isEmpty(doctorId)){
            throw new TipsException("预约包含非生美项目,需选择预约医生!");
        }
        /////////////////////////////////////////////////
@@ -230,10 +244,10 @@
        // int sxTime = 5;
        sql.setLength(0);
        sql.append(" select * from cure_set_time ");
        sql.append(" where isDel = #{m.isDel} and appType = #{m.appType} and userLevel = #{m.userLevel}");
        sql.append(" where isDel = #{m.isDel} and appType = #{m.appType} and memberLevelId = #{m.memberLevelId}");
        values.put("isDel", BaseEntity.NO);
        values.put("appType", dto.getAppType());
        values.put("userLevel", user.getUserLevel());
        values.put("memberLevelId", user.getMemberLevelId());
        sqlSentence.setSqlSentence(sql.toString());
        List<CureSetTime> cList = commonService.selectList(CureSetTimeMapper.class, sqlSentence);
@@ -297,9 +311,11 @@
        //用户操作时,对应个别时间为0
        if(dto.getOpType() == OperatorConstants.OP_TYPE_USER){
            mzTime = 0;
//            mzTime = 0;
            //默认标准轮匹配的实际面诊时长=系统面诊时长
            dto.setRealMzTime(mzTime);
            gtTime = 0;
            sqTime = 0;
//            sqTime = 0;
            waitDuration = 0;
        }
        //再生项目时,其他时间都为0
@@ -345,7 +361,7 @@
            err = TransferUtil.checkTransferNotAccepted(commonService
                    , user, shop, st, doctor, cu, projectList);
            if(err != null){
                throwParamException(err);
                throw new TipsException(err);
            }
            //修改为转疗
@@ -447,7 +463,7 @@
        timeMap = mateData.getTimeMap();
        err = mateData.getErrMsg();
        if(timeMap == null || timeMap.size() <= 0){
            throw new TipsException("当前日期医生没有可用时间");
            throw new TipsException("当前预约医生预约日期无排班时间,无法选择系统推荐时间,请重新选择预约医生");
        }
        ////////////////////////////////////////////////////////////////////////
@@ -461,7 +477,7 @@
        }
        ApponintmentVo aVo = null;
        ApponintmentVo aVo2 = null;
//        ApponintmentVo aVo2 = null;
        String deviceErr = null;
        //从医生可用时间里面,拼接出当天最小可以时间
@@ -483,7 +499,7 @@
        String doctorTimeAppNumSql = sql.toString();
        //超过2个停止循环
        while(aVoList.size() < 2 && StringUtils.isEmpty(err)){
        while(aVoList.size() < dto.getMateNum() && StringUtils.isEmpty(err)){
            //每次匹配都判断一下是否要做上下午时间处理
            mateData = AppAutoMateHandleUtil.handleTimeToDaySpace(timeMap, dto.getArriveDate(), daySpaceType, palsyDuration, st);
            timeMap = mateData.getTimeMap();
@@ -509,13 +525,13 @@
            //为空,表示当天已经没有时间段可以预约
            if(aVo == null && upOrDown != 0)
            {
                if (aVoList.size() < 2 && handleNum == 1 && deductHandle) {
                if (aVoList.size() < dto.getMateNum() && handleNum == 1 && deductHandle) {
                    //第二轮(治疗开始时间+10分钟)
                    handleNum = 2;
                    mateData = AppAutoMateHandleUtil.handleTime(commonService, shopWorkTimeVo, activityDay, projectIdsArr, doctorTimeList, shopTimeList
                            , doctorId, dto.getShopId(), handleNum, canAppList);
                    timeMap = mateData.getTimeMap();
                } else if (aVoList.size() < 2 && handleNum == 2 && deductHandle) {
                } else if (aVoList.size() < dto.getMateNum() && handleNum == 2 && deductHandle) {
                    //第三轮(治疗结束时间-10分钟)
                    handleNum = 3;
                    mateData = AppAutoMateHandleUtil.handleTime(commonService, shopWorkTimeVo, activityDay, projectIdsArr, doctorTimeList, shopTimeList
@@ -523,7 +539,7 @@
                    timeMap = mateData.getTimeMap();
                }
                //如果是处理到:向上处理+没满足2个+(第三轮后 或 非扣减处理),则跑向下处理(+等待时间)
                else if(upOrDown == 2 && aVoList.size() < 2 && (handleNum == 3 || !deductHandle)) {
                else if(upOrDown == 2 && aVoList.size() < dto.getMateNum() && (handleNum == 3 || !deductHandle)) {
                    //修改向上匹配时间
                    upOrDown = 1;
                    handleNum = 1;
@@ -595,15 +611,21 @@
                        //判断相同向下匹配
                        if(aVoList.size() > 0)
                        {
                            aVo2 = aVoList.get(0);
                            //遍历判断匹配时间是否重复,
                            boolean isRepeat = false;
                            for(ApponintmentVo apponintmentVo : aVoList){
                                if(
                                        (apponintmentVo.getStartTime().compareTo(aVo.getStartTime()) == 0 && apponintmentVo.getEndTime().compareTo(aVo.getEndTime()) == 0)
                                    // || (aVo2.getMzStartTime().compareTo(aVo.getMzStartTime()) == 0 && aVo2.getMzEndTime().compareTo(aVo.getMzEndTime()) == 0)
                                    // || (aVo2.getZlStartTime().compareTo(aVo.getZlStartTime()) ==0 && aVo2.getEndTime().compareTo(aVo.getEndTime()) == 0)
                                ){
                                    isRepeat = true;
                                   break;
                                }
                            }
                            if(
                                    (aVo2.getStartTime().compareTo(aVo.getStartTime()) == 0 && aVo2.getEndTime().compareTo(aVo.getEndTime()) == 0)
                                // || (aVo2.getMzStartTime().compareTo(aVo.getMzStartTime()) == 0 && aVo2.getMzEndTime().compareTo(aVo.getMzEndTime()) == 0)
                                // || (aVo2.getZlStartTime().compareTo(aVo.getZlStartTime()) ==0 && aVo2.getEndTime().compareTo(aVo.getEndTime()) == 0)
                            ){
                                upOrDown = 1;
                            }else{
                            //不重复则,存储对应可用
                            if(!isRepeat){
                                aVo.setHandleNum(handleNum);
                                aVo.setUpOrDown(upOrDown);
                                aVo.setProjectIds(projectIds);
@@ -624,6 +646,9 @@
                                    //如果是下午分隔的可以跳过
                                    break;
                                }
                            }else{
                                //重复则向下匹配
                                upOrDown = 1;
                            }
                        }else{
                            aVo.setHandleNum(handleNum);
@@ -653,7 +678,7 @@
                }
                //如果检查返回有不符合的条件
                if(upOrDown == 1 && aVoList.size() < 2){
                if(upOrDown == 1 && aVoList.size() < dto.getMateNum()){
                    //向下
                    //已面诊开始时间为开头加5分钟重新判断
                    cs.setTime(aVo.getMzStartTime());
@@ -663,7 +688,7 @@
                }
                // else if(upOrDown == 2 && aVoList.size() == 1){
                //     break;
                else if(upOrDown == 2 && aVoList.size() < 2){
                else if(upOrDown == 2 && aVoList.size() < dto.getMateNum()){
                    //向上
                    //已初始向上开始时间为开头减5分钟重新判断
                    cs.setTime(aVo.getMzStartTime());
@@ -726,7 +751,7 @@
        }else{
            json.put("errMsg", deviceErr);
        }
        logger.info("预约匹配返回结果:{}", json.toString());
        return Result.success(json);
    }
phi_platform_user/src/main/java/com/hx/phip/controller/appointment/AppointmentController.java
@@ -4,7 +4,6 @@
import com.alibaba.fastjson.JSONObject;
import com.hx.common.BaseController;
import com.hx.exception.TipsException;
import com.hx.guide.util.AppointmentListUtil;
import com.hx.guide.util.CommonQueryUtil;
import com.hx.mybatisTool.SqlSentence;
import com.hx.phiappt.common.OperatorConstants;
@@ -12,12 +11,10 @@
import com.hx.phiappt.common.UserStatusConstants;
import com.hx.phiappt.constants.tool.appointment.AppointmentTool;
import com.hx.phiappt.constants.tool.appointment.TransferUtil;
import com.hx.phiappt.constants.tool.appointment.autoMate.AppAutoMateV5Util;
import com.hx.phiappt.dao.mapper.*;
import com.hx.phiappt.model.*;
import com.hx.phiappt.util.AppointmentV2Util;
import com.hx.phiappt.vo.OperatorVo;
import com.hx.phiappt.vo.ProjectVo;
import com.hx.phip.service.EmployeeRoleService;
import com.hx.phip.service.EmployeeService;
import com.hx.phip.service.SystemParameterService;
@@ -26,10 +23,7 @@
import com.hx.resultTool.Result;
import com.hx.util.DateUtil;
import com.hx.util.StringUtils;
import com.hz.his.dto.appointment.AppointmentCrmAddDto;
import com.hz.his.dto.appointment.AppointmentV2Dto;
import com.platform.exception.PlatTipsException;
import com.platform.resultTool.PlatformCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.RequestBody;
@@ -59,239 +53,6 @@
    private EmployeeRoleService employeeRoleService;
    @Resource
    private EmployeeService employeeService;
    /** CRM预约(CRM的再升美学预约) */
    @RequestMapping("/crm/app")
    public Result crmApp(@RequestBody(required = false) AppointmentCrmAddDto dto) {
        if (dto == null) {
             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "请求参数为空!");
        }
        if(dto.getHandleType() == null){
             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "处理类型不能为空!");
        }
        Appointment appointment = null;
        //判断处理类型处理类型(1新增2编辑3取消)
        if(dto.getHandleType() == 2 || dto.getHandleType() == 3){
            if(StringUtils.isEmpty(dto.getAppointmentId())){
                throw new PlatTipsException(PlatformCode.ERROR_TIPS, "预约标识不能为空!");
            }
            appointment = commonService.selectOneByKey(AppointmentMapper.class, dto.getAppointmentId());
            if(appointment == null){
                throw new PlatTipsException(PlatformCode.ERROR_TIPS, "查询不到预约信息!");
            }
            //如果处理类型为取消,则直接调用取消逻辑然后返回
            if(dto.getHandleType() == 3){
                appointmentService.cancel(appointment, dto.getRemark(), Appointment.CANCEL_TYPE_CRM_USER, null);
                return Result.success();
            }
        }
        if(StringUtils.isEmpty(dto.getUserId())){
             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "用户标识为空!");
        }
        if(StringUtils.isEmpty(dto.getShopId())){
             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "门店标识为空!");
        }
        if(StringUtils.isEmpty(dto.getDoctorId())){
             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "医生标识为空!");
        }
        if(StringUtils.isEmpty(dto.getStartTime())){
             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "开始时间为空!");
        }
        User user = commonService.selectOneByKeyBlob(UserMapper.class, dto.getUserId());
        if (user == null) {
             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "找不到用户信息!");
        }
        Shop shop = commonService.selectOneByKeyBlob(ShopMapper.class, dto.getShopId());
        if (shop == null) {
             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "找不到门店信息!");
        }
        Employee employee = commonService.selectOneByKeyBlob(EmployeeMapper.class, dto.getDoctorId());
        if (employee == null) {
            throw new PlatTipsException(PlatformCode.ERROR_TIPS, "找不到医生信息!");
        }
        //目前写死一个项目
        SystemParameter sp = systemParameterService.selectOneByName(SystemParameter.KEY_CRM_APPOINTMENT_PROJECT_ID);
        if(sp == null || StringUtils.isEmpty(sp.getParamValue())){
            throw new PlatTipsException(PlatformCode.ERROR_TIPS, "还未配置项目信息!");
        }
        Project project = commonService.selectOneByKey(ProjectMapper.class, sp.getParamValue());
        if(project == null){
             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "找不到项目信息!");
        }
        if(project == null || project.getIsDel() == BaseEntity.YES || project.getIsUp() == BaseEntity.NO)
        {
             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "找不到项目或者项目下架!");
        }
        //组装json数组
        JSONArray arr = new JSONArray();
        JSONObject temp = new JSONObject();
        temp.put("id", project.getId());
        temp.put("num", 1);
        temp.put("isLifeBeauty", project.getIsLifeBeauty());
        temp.put("name", project.getName());
        temp.put("palsyDuration", project.getPalsyDuration());
        temp.put("isPalsy", project.getPalsyDuration() > 0 ? 1 : 0);
        temp.put("useDuration", project.getUseDuration());
        arr.add(temp);
        String [] projectIdsArr =  new String[arr.size()];
        String [] projectNamesArr = new String[arr.size()];
        Map<String, Integer> pNumMap = new HashMap<>();
        Map<String, Integer> pZlMap = new HashMap<>();
        String id = null;
        int num = 0;
        int zlTime = 0;
        List<AppointmentProject> apList = new ArrayList<>();
        LinkedHashMap<String, ProjectVo> pMap = new LinkedHashMap<>();
        for(int i = 0; i < arr.size(); i ++)
        {
            temp = arr.getJSONObject(i);
            id = temp.getString("id");
            num = temp.getIntValue("num");
            if(StringUtils.isEmpty(id) || num <= 0)
            {
                 throw new PlatTipsException(PlatformCode.ERROR_TIPS, "请选择正确项目和数量");
            }
            project = commonService.selectOneByKey(ProjectMapper.class, id);
            if(project == null || project.getIsDel() == BaseEntity.YES || project.getIsUp() == BaseEntity.NO)
            {
                 throw new PlatTipsException(PlatformCode.ERROR_TIPS, "找不到项目或者项目下架");
            }
//            //获取最大的术前准备时间
//            if(project.getReadyDuration() > sqTime){
//                sqTime = project.getReadyDuration();
//            }
            pNumMap.put(id, num);
            //判断治疗时间等于0,则默认5分钟
            pZlMap.put(id, project.getUseDuration() == null ? 0 : project.getUseDuration());
            pMap.put(id, new ProjectVo(project, num, dto.getShopId()));
            pMap.get(id).setZlTime(project.getUseDuration() / 60);
            projectIdsArr[i] = id;
            projectNamesArr[i] = project.getName();
            apList.add(new AppointmentProject(id, num));
            //治疗时间(分钟) = 项目使用时长(秒) / 60
            zlTime += project.getUseDuration() / 60;
        }
        SqlSentence sqlSentence = new SqlSentence();
        Map<String, Object> values = new HashMap<>();
        sqlSentence.setM(values);
        AppointmentInfo appointmentInfo = new AppointmentInfo();
        if(appointment == null){
            appointment = new Appointment();
        }
        appointment.setStatus(Appointment.STATUS_SUC);
        appointment.setSourceId(dto.getSourceId());
        appointment.setShopId(dto.getShopId());
        appointment.setDoctorId(dto.getDoctorId());
        appointment.setUserId(dto.getUserId());
        //项目信息
        appointment.setProjectJson(arr.toJSONString());
        appointment.setProjectIds(org.apache.commons.lang.StringUtils.join(projectIdsArr,","));
        appointment.setProjectNames(org.apache.commons.lang.StringUtils.join(projectNamesArr,","));
        //时间信息
        appointment.setStartTime(DateUtil.parseString_1(dto.getStartTime()));
        appointment.setEndTime(DateUtil.parseString_1(dto.getEndTime()));
        appointment.setDayStr(DateUtil.formatDate(appointment.getStartTime()));
        //周字符串
        Calendar ca = Calendar.getInstance();
        ca.setTime(appointment.getStartTime());
        int dayOfWeek = ca.get(Calendar.DAY_OF_WEEK);
        if(dayOfWeek == 1)
        {
            ca.add(Calendar.DAY_OF_YEAR, -6);
        }else{
            ca.add(Calendar.DAY_OF_YEAR, 2 - dayOfWeek);
        }
        appointment.setWeekStr(DateUtil.formatDate(ca.getTime()));
        appointment.setMonthStr(appointment.getDayStr().substring(0, 6));
        //所属顾问,使用用户所属顾问
        appointment.setCorpUserId(user.getHisCorpUserId());
        //创建人信息
        appointment.setCreateManId(user.getId());
        appointment.setCreateManName(user.getName());
        appointment.setCreateManType(Appointment.CREATE_MAN_TYPE_USER);
        //默认就诊类型:医美
        appointment.setVisitType("医美");
        //备注
        appointment.setRemark(dto.getRemark());
        //新增模式
        appointment.setAddMode(Appointment.ADD_MODE_CRM_CREATE);
        //
        appointment.setComDuration(0);
        appointment.setDocComDuration(0);
        appointment.setReadyDuration(0);
        appointment.setProDuration(0);
        appointment.setPalsyDuration(0);
        appointment.setTreatDuration(zlTime);
        appointment.setDoctorZlDuration(zlTime);
        //总时长 = 面诊 + 沟通 + 敷麻 + 术前 + 准备等待 + 治疗
        int duration = appointment.getDocComDuration() + appointment.getComDuration() + appointment.getPalsyDuration() + appointment.getReadyDuration() + appointment.getWaitDuration() + appointment.getTreatDuration();
        appointment.setDuration(duration);
        //获取出医生的治疗时间记录
        JSONArray zlTimeJson = AppAutoMateV5Util.handleDoctorZlTime(pMap, appointment.getStartTime());
        appointmentInfo.setZlTimeJson(zlTimeJson.toString());
        List<DoctorTime> doctorTimeList = AppointmentV2Util.getDoctorZlTime(zlTimeJson.toString(), appointment.getShopId(), appointment.getDoctorId(), appointment.getDayStr(), appointment.getMonthStr());
        //新增时
        if(StringUtils.isEmpty(appointment.getId())){
            //冗余用户信息
            appointmentInfo.setUserStatus(user.getUserStatus());
            appointmentInfo.setUserStatusCn(UserStatusConstants.getName(user.getUserStatus()));
            appointmentInfo.setUserInternetCorpUserId(user.getInternetCorpUserId());
            appointmentInfo.setUserInternetCorpUserName(CommonQueryUtil.getEmployeeName(user.getInternetCorpUserId(), commonService));
            appointmentInfo.setUserConsultantId(user.getHisCorpUserId());
            appointmentInfo.setUserConsultantName(CommonQueryUtil.getEmployeeName(user.getHisCorpUserId(), commonService));
            appointmentInfo.setUserShopId(user.getShopId());
            appointmentInfo.setUserShopName(CommonQueryUtil.getShopName(user.getShopId(), commonService));
            appointmentInfo.setUserLevel(user.getUserLevel());
            appointmentInfo.setMemberLevelId(user.getMemberLevelId());
            //根据用户角色信息,获取对应可使用预约类型,多个取第一个
            net.sf.json.JSONArray appTypeArr = AppointmentListUtil.userToAppType(dto.getUserId(), commonService);
            if(appTypeArr == null || appTypeArr.size() < 1){
                 throw new PlatTipsException(PlatformCode.ERROR_TIPS, "没有对应预约类型!");
            }
            appointment.setAppType(appTypeArr.getInt(0));
        }
        //添加预约
        if(dto.getHandleType() == 1){
            appointmentService.crmAdd(appointment, apList, doctorTimeList, null, appointmentInfo);
        }else if(dto.getHandleType() == 2){
            appointmentService.crmEdit(appointment, appointmentInfo, 0, doctorTimeList, apList, null, null);
        }
        JSONObject data = new JSONObject();
        data.put("appointmentId", appointment.getId());
        return Result.success(data);
    }
    /** 新增预约 */
    @RequestMapping("/add")
@@ -324,8 +85,10 @@
            throw new TipsException("请选择预约类型!");
        }
        if (dto.getIsMicApprove() == BaseEntity.YES && StringUtils.isEmpty(dto.getImgUrls())){
            throw new TipsException("MIC同意必须选择图片!");
        if (dto.getIsMicApprove() == BaseEntity.YES){
            if(dto.getAddMode() == Appointment.ADD_MODE_ADVISER_V2_3 && StringUtils.isEmpty(dto.getImgUrls())){
                throw new TipsException("MIC同意必须选择图片!");
            }
        }
        String corpUserId = StringUtils.isEmpty(dto.getCorpUserId()) ? null : dto.getCorpUserId();
@@ -487,6 +250,8 @@
        }
        //周,取当前周一
        appointment.setWeekStr(DateUtil.formatDate(getWeekDate(st)));
        //预约冲突原因
        appointment.setConflictReason(dto.getConflictReason());
        //处理预约状态和是否转疗逻辑
        handleStatusAndIsSwitch(dto.getAddMode(), appointment, shop, employee, false, null);
@@ -748,8 +513,23 @@
        List<AppointmentProjectDeviceNo> apdnList = new ArrayList<>();
        List<DeviceNoSchedule> dnsList = AppointmentV2Util.handleDeviceTime(dto.getDeviceTimeJson(), apdnList);
        //获取出医生的治疗时间记录
        List<DoctorTime> doctorTimeList = AppointmentV2Util.getDoctorZlTime(dto.getZlTimeJson(), dto.getShopId(), dto.getDoctorId(), dayStr, dayStr.substring(0, 6));
        List<DoctorTime> doctorTimeList = null;
        //后台预约时,zlTimeJson没有对应的开始结束时间,所以要特殊处理
        if(dto.getAddMode() == Appointment.ADD_MODE_BACKSTAGE_V2_3){
            List<Integer> doctorZlTime = new ArrayList<>();
            doctorZlTime.add(0);
            net.sf.json.JSONArray newZlTimeJson = new net.sf.json.JSONArray();
            //治疗开始时间
            ca.setTime(st);
            ca.add(Calendar.MINUTE, duration - dto.getZlTime());
            Date treatSt = ca.getTime();
            doctorTimeList = AppointmentV2Util.getDoctorZlTime(dto.getZlTimeJson(), treatSt
                    , dto.getDoctorId(), dto.getShopId(), dayStr , appointment.getMonthStr(), doctorZlTime
                    , newZlTimeJson, dnsList);
            appointment.setDoctorZlDuration(doctorZlTime.get(0));
        }else{
            doctorTimeList = AppointmentV2Util.getDoctorZlTime(dto.getZlTimeJson(), dto.getShopId(), dto.getDoctorId(), dayStr, dayStr.substring(0, 6));
        }
//        if(isChangeTime == 1 || dto.getIsProjectChange() == 1) {
//            String [] projectIdsArr = StringUtils.isEmpty(dto.getProjectIds()) ? new String[0] : dto.getProjectIds().split(",");
@@ -793,6 +573,7 @@
        appointment.setProjectJson(dto.getProjectJson());
        appointment.setComRoomId(dto.getComRoomId());
        appointment.setTreatRoomId(dto.getTreatRoomId());
        appointment.setConflictReason(dto.getConflictReason());
        //如果预约已审核,则记录一下已审核修改
        if(appointment.getStatus() == Appointment.STATUS_SUC || appointment.getStatus() == Appointment.STATUS_FAIL) {
            appointment.setIsModify(BaseEntity.YES);
@@ -951,21 +732,24 @@
    //处理预约状态和是否转疗逻辑
    private void handleStatusAndIsSwitch(Integer addMode, Appointment appointment, Shop shop, Employee employee, boolean isEdit, Appointment oldInfo) {
        //默认状态:待审核
        appointment.setStatus(Appointment.STATUS_WAIT);
        //CRM预约的默认状态:预约成功
        if(addMode == Appointment.ADD_MODE_CRM_SELF){
            appointment.setStatus(Appointment.STATUS_SUC);
            return;
        }
        //非HIS助手顾问新增 或 要MIC同意的则跳过
        if(addMode != Appointment.ADD_MODE_ADVISER_V2_3 || appointment.getIsMicApprove() == BaseEntity.YES){
        //要MIC同意的则跳过
        if(appointment.getIsMicApprove() == BaseEntity.YES){
            return;
        }
        //默认状态:待审核
        appointment.setStatus(Appointment.STATUS_WAIT);
        //要MIC同意跳过
        if(appointment.getIsModify() == BaseEntity.YES){
        //非HIS助手顾问新增、后台信息的
        if(addMode != Appointment.ADD_MODE_ADVISER_V2_3
                && addMode != Appointment.ADD_MODE_BACKSTAGE_V2_3
                && addMode != Appointment.ADD_MODE_BACKSTAGE_V2_4){
            return;
        }
@@ -1099,4 +883,239 @@
        }
    }
    //
//    /** CRM预约(CRM的再升美学预约) */
//    @RequestMapping("/crm/app")
//    public Result crmApp(@RequestBody(required = false) AppointmentCrmAddDto dto) {
//
//        if (dto == null) {
//             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "请求参数为空!");
//        }
//
//        if(dto.getHandleType() == null){
//             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "处理类型不能为空!");
//        }
//
//        Appointment appointment = null;
//        //判断处理类型处理类型(1新增2编辑3取消)
//        if(dto.getHandleType() == 2 || dto.getHandleType() == 3){
//            if(StringUtils.isEmpty(dto.getAppointmentId())){
//                throw new PlatTipsException(PlatformCode.ERROR_TIPS, "预约标识不能为空!");
//            }
//
//            appointment = commonService.selectOneByKey(AppointmentMapper.class, dto.getAppointmentId());
//            if(appointment == null){
//                throw new PlatTipsException(PlatformCode.ERROR_TIPS, "查询不到预约信息!");
//            }
//
//            //如果处理类型为取消,则直接调用取消逻辑然后返回
//            if(dto.getHandleType() == 3){
//                appointmentService.cancel(appointment, dto.getRemark(), Appointment.CANCEL_TYPE_CRM_USER, null);
//                return Result.success();
//            }
//        }
//
//        if(StringUtils.isEmpty(dto.getUserId())){
//             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "用户标识为空!");
//        }
//
//        if(StringUtils.isEmpty(dto.getShopId())){
//             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "门店标识为空!");
//        }
//
//        if(StringUtils.isEmpty(dto.getDoctorId())){
//             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "医生标识为空!");
//        }
//
//        if(StringUtils.isEmpty(dto.getStartTime())){
//             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "开始时间为空!");
//        }
//
//        User user = commonService.selectOneByKeyBlob(UserMapper.class, dto.getUserId());
//        if (user == null) {
//             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "找不到用户信息!");
//        }
//
//        Shop shop = commonService.selectOneByKeyBlob(ShopMapper.class, dto.getShopId());
//        if (shop == null) {
//             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "找不到门店信息!");
//        }
//
//        Employee employee = commonService.selectOneByKeyBlob(EmployeeMapper.class, dto.getDoctorId());
//        if (employee == null) {
//            throw new PlatTipsException(PlatformCode.ERROR_TIPS, "找不到医生信息!");
//        }
//
//        //目前写死一个项目
//        SystemParameter sp = systemParameterService.selectOneByName(SystemParameter.KEY_CRM_APPOINTMENT_PROJECT_ID);
//        if(sp == null || StringUtils.isEmpty(sp.getParamValue())){
//            throw new PlatTipsException(PlatformCode.ERROR_TIPS, "还未配置项目信息!");
//        }
//
//        Project project = commonService.selectOneByKey(ProjectMapper.class, sp.getParamValue());
//        if(project == null){
//             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "找不到项目信息!");
//        }
//
//        if(project == null || project.getIsDel() == BaseEntity.YES || project.getIsUp() == BaseEntity.NO)
//        {
//             throw new PlatTipsException(PlatformCode.ERROR_TIPS, "找不到项目或者项目下架!");
//        }
//
//        //组装json数组
//        JSONArray arr = new JSONArray();
//        JSONObject temp = new JSONObject();
//        temp.put("id", project.getId());
//        temp.put("num", 1);
//        temp.put("isLifeBeauty", project.getIsLifeBeauty());
//        temp.put("name", project.getName());
//        temp.put("palsyDuration", project.getPalsyDuration());
//        temp.put("isPalsy", project.getPalsyDuration() > 0 ? 1 : 0);
//        temp.put("useDuration", project.getUseDuration());
//        arr.add(temp);
//
//        String [] projectIdsArr =  new String[arr.size()];
//        String [] projectNamesArr = new String[arr.size()];
//        Map<String, Integer> pNumMap = new HashMap<>();
//        Map<String, Integer> pZlMap = new HashMap<>();
//        String id = null;
//        int num = 0;
//        int zlTime = 0;
//
//
//        List<AppointmentProject> apList = new ArrayList<>();
//        LinkedHashMap<String, ProjectVo> pMap = new LinkedHashMap<>();
//        for(int i = 0; i < arr.size(); i ++)
//        {
//            temp = arr.getJSONObject(i);
//            id = temp.getString("id");
//            num = temp.getIntValue("num");
//            if(StringUtils.isEmpty(id) || num <= 0)
//            {
//                 throw new PlatTipsException(PlatformCode.ERROR_TIPS, "请选择正确项目和数量");
//            }
//            project = commonService.selectOneByKey(ProjectMapper.class, id);
//            if(project == null || project.getIsDel() == BaseEntity.YES || project.getIsUp() == BaseEntity.NO)
//            {
//                 throw new PlatTipsException(PlatformCode.ERROR_TIPS, "找不到项目或者项目下架");
//            }
////            //获取最大的术前准备时间
////            if(project.getReadyDuration() > sqTime){
////                sqTime = project.getReadyDuration();
////            }
//            pNumMap.put(id, num);
//            //判断治疗时间等于0,则默认5分钟
//            pZlMap.put(id, project.getUseDuration() == null ? 0 : project.getUseDuration());
//            pMap.put(id, new ProjectVo(project, num, dto.getShopId()));
//            pMap.get(id).setZlTime(project.getUseDuration() / 60);
//            projectIdsArr[i] = id;
//            projectNamesArr[i] = project.getName();
//            apList.add(new AppointmentProject(id, num));
//            //治疗时间(分钟) = 项目使用时长(秒) / 60
//            zlTime += project.getUseDuration() / 60;
//        }
//
//        SqlSentence sqlSentence = new SqlSentence();
//        Map<String, Object> values = new HashMap<>();
//        sqlSentence.setM(values);
//
//        AppointmentInfo appointmentInfo = new AppointmentInfo();
//        if(appointment == null){
//            appointment = new Appointment();
//        }
//        appointment.setStatus(Appointment.STATUS_SUC);
//        appointment.setSourceId(dto.getSourceId());
//        appointment.setShopId(dto.getShopId());
//        appointment.setDoctorId(dto.getDoctorId());
//        appointment.setUserId(dto.getUserId());
//        //项目信息
//        appointment.setProjectJson(arr.toJSONString());
//        appointment.setProjectIds(org.apache.commons.lang.StringUtils.join(projectIdsArr,","));
//        appointment.setProjectNames(org.apache.commons.lang.StringUtils.join(projectNamesArr,","));
//        //时间信息
//        appointment.setStartTime(DateUtil.parseString_1(dto.getStartTime()));
//        appointment.setEndTime(DateUtil.parseString_1(dto.getEndTime()));
//        appointment.setDayStr(DateUtil.formatDate(appointment.getStartTime()));
//        //周字符串
//        Calendar ca = Calendar.getInstance();
//        ca.setTime(appointment.getStartTime());
//        int dayOfWeek = ca.get(Calendar.DAY_OF_WEEK);
//        if(dayOfWeek == 1)
//        {
//            ca.add(Calendar.DAY_OF_YEAR, -6);
//        }else{
//            ca.add(Calendar.DAY_OF_YEAR, 2 - dayOfWeek);
//        }
//        appointment.setWeekStr(DateUtil.formatDate(ca.getTime()));
//        appointment.setMonthStr(appointment.getDayStr().substring(0, 6));
//        //所属顾问,使用用户所属顾问
//        appointment.setCorpUserId(user.getHisCorpUserId());
//        //创建人信息
//        appointment.setCreateManId(user.getId());
//        appointment.setCreateManName(user.getName());
//        appointment.setCreateManType(Appointment.CREATE_MAN_TYPE_USER);
//        //默认就诊类型:医美
//        appointment.setVisitType("医美");
//        //备注
//        appointment.setRemark(dto.getRemark());
//        //新增模式
//        appointment.setAddMode(Appointment.ADD_MODE_CRM_CREATE);
//
//        //
//        appointment.setComDuration(0);
//        appointment.setDocComDuration(0);
//        appointment.setReadyDuration(0);
//        appointment.setProDuration(0);
//        appointment.setPalsyDuration(0);
//        appointment.setTreatDuration(zlTime);
//        appointment.setDoctorZlDuration(zlTime);
//
//        //总时长 = 面诊 + 沟通 + 敷麻 + 术前 + 准备等待 + 治疗
//        int duration = appointment.getDocComDuration() + appointment.getComDuration() + appointment.getPalsyDuration() + appointment.getReadyDuration() + appointment.getWaitDuration() + appointment.getTreatDuration();
//        appointment.setDuration(duration);
//
//        //获取出医生的治疗时间记录
//        JSONArray zlTimeJson = AppAutoMateV5Util.handleDoctorZlTime(pMap, appointment.getStartTime());
//        appointmentInfo.setZlTimeJson(zlTimeJson.toString());
//        List<DoctorTime> doctorTimeList = AppointmentV2Util.getDoctorZlTime(zlTimeJson.toString(), appointment.getShopId(), appointment.getDoctorId(), appointment.getDayStr(), appointment.getMonthStr());
//
//
//        //新增时
//        if(StringUtils.isEmpty(appointment.getId())){
//
//            //冗余用户信息
//            appointmentInfo.setUserStatus(user.getUserStatus());
//            appointmentInfo.setUserStatusCn(UserStatusConstants.getName(user.getUserStatus()));
//            appointmentInfo.setUserInternetCorpUserId(user.getInternetCorpUserId());
//            appointmentInfo.setUserInternetCorpUserName(CommonQueryUtil.getEmployeeName(user.getInternetCorpUserId(), commonService));
//            appointmentInfo.setUserConsultantId(user.getHisCorpUserId());
//            appointmentInfo.setUserConsultantName(CommonQueryUtil.getEmployeeName(user.getHisCorpUserId(), commonService));
//            appointmentInfo.setUserShopId(user.getShopId());
//            appointmentInfo.setUserShopName(CommonQueryUtil.getShopName(user.getShopId(), commonService));
//            appointmentInfo.setUserLevel(user.getUserLevel());
//            appointmentInfo.setMemberLevelId(user.getMemberLevelId());
//
//            //根据用户角色信息,获取对应可使用预约类型,多个取第一个
//            net.sf.json.JSONArray appTypeArr = AppointmentListUtil.userToAppType(dto.getUserId(), commonService);
//            if(appTypeArr == null || appTypeArr.size() < 1){
//                 throw new PlatTipsException(PlatformCode.ERROR_TIPS, "没有对应预约类型!");
//            }
//            appointment.setAppType(appTypeArr.getInt(0));
//        }
//
//        //添加预约
//        if(dto.getHandleType() == 1){
//            appointmentService.crmAdd(appointment, apList, doctorTimeList, null, appointmentInfo);
//        }else if(dto.getHandleType() == 2){
//            appointmentService.crmEdit(appointment, appointmentInfo, 0, doctorTimeList, apList, null, null);
//        }
//
//
//        JSONObject data = new JSONObject();
//        data.put("appointmentId", appointment.getId());
//
//        return Result.success(data);
//    }
}
phi_platform_user/src/main/java/com/hx/phip/controller/appointment/CrmSelfV2Controller.java
New file
@@ -0,0 +1,438 @@
package com.hx.phip.controller.appointment;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hx.common.BaseController;
import com.hx.exception.TipsException;
import com.hx.mybatisTool.SqlSentence;
import com.hx.phiappt.common.OperatorConstants;
import com.hx.phiappt.constants.tool.user.UserTool;
import com.hx.phiappt.dao.mapper.*;
import com.hx.phiappt.model.*;
import com.hx.phip.config.GlobalExceptionHandler;
import com.hx.resultTool.Result;
import com.hx.util.DateUtil;
import com.hx.util.StringUtils;
import com.hz.his.dto.appointment.AppointmentAutoMateDto;
import com.hz.his.dto.appointment.AppointmentDto;
import com.hz.his.dto.appointment.AppointmentV2Dto;
import com.hz.his.dto.user.UserDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * CRM自助预约v2
 * 按phis医生排班和预约项目进行预约
 * @USER: fhx
 * @DATE: 2024/4/3
 **/
@Slf4j
@RestController
@RequestMapping("/appointment/crm/self/v2")
public class CrmSelfV2Controller extends BaseController {
    @Resource
    private AppAutoMateController appAutoMateController;
    @Resource
    private AppointmentController appointmentController;
    public static final String FORMAT = "yyyy-MM-ddHH:mm";
    /** 预约门店 */
    @RequestMapping("/shop/list")
    public Result shopList(){
        SqlSentence sqlSentence = new SqlSentence();
        sqlSentence.setSqlSentence(" select id, name, workTime from shop where isDel = 0 and isUp = 1 ");
        List<Map<String, Object>> list = commonService.selectListMap(ShopMapper.class, sqlSentence);
        Map<String, Object> data = new HashMap<>();
        data.put("list", list);
        return Result.success(data);
    }
    /** 医生排班 */
    @RequestMapping("/doctor/time/list")
    public Result doctorTimeList(@RequestBody AppointmentAutoMateDto dto){
        if(StringUtils.isEmpty(dto.getShopId())){
            throw new TipsException("门店标识为空!");
        }
        if(StringUtils.isEmpty(dto.getStartTime())){
            throw new TipsException("开始时间为空!");
        }
        if(StringUtils.isEmpty(dto.getEndTime())){
            throw new TipsException("结束时间为空!");
        }
//        //版本1返回
//        return Result.success(doctorTimeListV1(dto));
        //版本2返回
        return Result.success(doctorTimeListV2(dto));
    }
    /** 预约项目SPU */
    @RequestMapping("/spu/list")
    public Result spuList(){
        SqlSentence sqlSentence = new SqlSentence();
        Map<String, Object> values = new HashMap<>();
        sqlSentence.setM(values);
        values.put("type", ProjectType.TYPE_APPOINTMENT);
        sqlSentence.setSqlSentence(" select id, name from project_general where isDel = 0 and type = #{m.type} and isUp = 1 order by orderNum asc ");
        List<Map<String, Object>> list = commonService.selectListMap(ProjectGeneralMapper.class, sqlSentence);
        Map<String, Object> data = new HashMap<>();
        data.put("list", list);
        return Result.success(data);
    }
    /** 预约项目 */
    @RequestMapping("/project/list")
    public Result projectList(@RequestBody AppointmentDto dto){
        if(dto.getPageSize() == null || dto.getPageSize() > 20){
            dto.setPageSize(20);
        }
        SqlSentence sqlSentence = new SqlSentence();
        Map<String, Object> values = new HashMap<>();
        sqlSentence.setM(values);
        values.put("type", ProjectType.TYPE_APPOINTMENT);
        StringBuilder sql = new StringBuilder();
        sql.append(" select p.id, p.name, p.isLifeBeauty, p.unit, p.specification  ")
                .append(", p.useDuration / 60 as useDuration ")
                .append(", p.palsyDuration / 60 as palsyDuration ")
                .append(", (p.useDuration + p.palsyDuration) / 60 as duration ")
//                .append(", (p.useDuration + p.palsyDuration + p.intervalDuration + p.readyDuration) / 60 as duration")
                .append(" from project p ")
                .append(" where p.isDel = 0 and p.isUp = 1 and p.isShow = 1 ")
                .append(" and p.type = #{m.type} ");
        if(StringUtils.noNull(dto.getKeyWord())){
            sql.append(" and p.name like '%").append(dto.getKeyWord()).append("%' ");
        }
        //spuId查询
        if(StringUtils.noNull(dto.getSpuId())){
            sql.append(" and p.projectGeneralId = '").append(dto.getSpuId()).append("' ");
        }
        sql.append(" order by p.orderNum asc ");
        sqlSentence.setSqlSentence(sql.toString());
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        List<Map<String, Object>> list = commonService.selectListMap(ProjectMapper.class, sqlSentence);
        PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(list);
        Map<String, Object> data = new HashMap<>();
        data.put("list", pageInfo.getList());
        data.put("pageNum", pageInfo.getPageNum());
        data.put("pageSize", pageInfo.getPageSize());
        data.put("pages", pageInfo.getPages());
        data.put("total", pageInfo.getTotal());
        data.put("isLastPage", pageInfo.isIsLastPage());
        return Result.success(data);
    }
    //////////////////////////////////////////////////////////////////////////////////////////
    /** 自助预约匹配时间 */
    @RequestMapping("/mate/time")
    public Result mateTime(@RequestBody AppointmentAutoMateDto dto){
        if(StringUtils.isEmpty(dto.getUserId())){
            throw new TipsException("预约用户标识为空!");
        }
        if(StringUtils.isEmpty(dto.getShopId())){
            throw new TipsException("预约门店标识为空!");
        }
        if(StringUtils.isEmpty(dto.getDoctorId())){
            throw new TipsException("预约医生标识为空!");
        }
        if(StringUtils.isEmpty(dto.getArriveDate())){
            throw new TipsException("预约日期为空!");
        }
        if(StringUtils.isEmpty(dto.getStartTime())){
            throw new TipsException("预约到店时间为空!");
        }
        if(StringUtils.isEmpty(dto.getProjectJson())){
            throw new TipsException("预约项目为空!");
        }
        Date startTime = DateUtil.parseString(dto.getArriveDate() + dto.getStartTime(), FORMAT);
        if(startTime == null){
            throw new TipsException("预约到店时间错误!");
        }
        //查询用户是否有到店记录
        dto.setOpType(OperatorConstants.OP_TYPE_USER);
        dto.setOpId(dto.getUserId());
        dto.setVisitType("医美");
        //判断用户没到店过,则初诊
        if(UserTool.getUserArrivalNum(commonService, dto.getUserId()) == 0){
            dto.setAppType(Appointment.APP_TYPE_FIRST);
        }else{
            dto.setAppType(Appointment.APP_TYPE_TREATMENT);
        }
        dto.setMateNum(3);
//        dto.setDaySpace(true);
        Result result;
        try{
            result = appAutoMateController.addApplyBland(dto);
        }catch (Exception e){
            log.info("获取用户自助预约时间失败:{}", GlobalExceptionHandler.getExceptionInformation(e));
            throw new TipsException("获取预约时间失败!");
        }
        //匹配报错提示文案
        JSONObject data = result.getJsonObject(result.getData());
        JSONArray arr = data.getJSONArray("list");
        if(arr != null && arr.size() > 0){
            data.remove("errMsg");
        }
        if(StringUtils.noNull(data.getString("errMsg")) ){
            throw new TipsException(data.getString("errMsg"));
        }
        return result;
    }
    /** 新增预约 */
    @RequestMapping("/add")
    public Result add(@RequestBody AppointmentV2Dto dto){
        if(StringUtils.isEmpty(dto.getUserId())){
            throw new TipsException("用户标识为空!");
        }
        dto.setOpId(dto.getUserId());
        dto.setOpType(OperatorConstants.OP_TYPE_USER); //操作人类型:用户
        dto.setAddMode(Appointment.ADD_MODE_CRM_SELF); //crm自助预约
        dto.setVisitType("医美");
        //判断用户没到店过,则初诊
        if(UserTool.getUserArrivalNum(commonService, dto.getUserId()) == 0){
            dto.setAppType(Appointment.APP_TYPE_FIRST);
        }else{
            dto.setAppType(Appointment.APP_TYPE_TREATMENT);
        }
        dto.setIsMicApprove(BaseEntity.NO); //无需MIC同意
        dto.setIsSendMsg(BaseEntity.YES); //发送短信通知
        dto.setIsArriveSendMsg(BaseEntity.YES); //发送短信通知
        //新增预约
        Result result = appointmentController.add(dto);
        if(!result.checkCode()){
            log.error("新增用户自助预约V2失败:{}", JSONObject.toJSONString(result));
            throw new TipsException("新增预约失败!");
        }
        JSONObject data = result.getJsonObject(result.getData());
        //查询返回对应预约信息
        SqlSentence sqlSentence = new SqlSentence();
        Map<String, Object> values = new HashMap<>();
        sqlSentence.setM(values);
        values.put("id", data.getString("id"));
        StringBuilder sql = new StringBuilder();
        sql.append(" select a.id, a.startTime, a.endTime , d.cnName as doctorName, a.doctorId ")
                .append(" , a.status, a.isArrive, a.projectNames, a.projectJson, a.addMode, a.createManName, a.createManType, remark ")
                .append(" , s.name as shopName, s.province, s.city, s.area, s.addr")
                .append(" from appointment a ")
                .append(" left join shop s on s.id = a.shopId ")
                .append(" left join employee d on d.id = a.doctorId ")
                .append(" where a.isDel = 0 and a.id = #{m.id}  ");
        sqlSentence.setSqlSentence(sql.toString());
        Map<String, Object> dataMap = commonService.selectOneMap(AppointmentMapper.class, sqlSentence);
        return Result.success(dataMap);
    }
    /** 取消预约 */
    @RequestMapping("/cancel")
    public Result cancel(@RequestBody AppointmentV2Dto dto){
        if(StringUtils.isEmpty(dto.getUserId())){
            throw new TipsException("用户标识为空!");
        }
        dto.setOpId(dto.getUserId());
        dto.setOpType(OperatorConstants.OP_TYPE_USER);
        return appointmentController.cancel(dto);
    }
    /** 用户预约列表 */
    @RequestMapping("/list")
    public Result list(@RequestBody UserDto dto){
        if(StringUtils.isEmpty(dto.getUserId())){
            throw new TipsException("用户标识为空!");
        }
        SqlSentence sqlSentence = new SqlSentence();
        Map<String, Object> values = new HashMap<>();
        sqlSentence.setM(values);
        values.put("userId", dto.getUserId());
        values.put("addMode9", Appointment.ADD_MODE_CRM_CREATE);
        StringBuilder sql = new StringBuilder();
        sql.append(" select a.id, a.startTime, a.endTime, d.cnName as doctorName, a.doctorId, a.addMode ")
                .append(" , a.status, a.isArrive, a.projectJson, a.addMode, a.createManName, a.createManType, a.remark ")
                .append(" , s.name as shopName, s.province, s.city, s.area, s.addr")
                .append(" from appointment a ")
                .append(" left join shop s on s.id = a.shopId ")
                .append(" left join employee d on d.id = a.doctorId ")
                .append(" where a.isDel = 0 and a.userId = #{m.userId}  ")
                //只查询预约成功和取消的
                .append(" and a.status in (").append(Appointment.STATUS_SUC).append(",").append(Appointment.STATUS_CANCEL).append(") ")
//                .append(" and a.addMode != #{m.addMode9} ")
                .append(" order by a.startTime desc ");
        sqlSentence.setSqlSentence(sql.toString());
        //分页插件
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        List<Map<String, Object>> list = commonService.selectListMap(AppointmentMapper.class, sqlSentence);
        PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(list);
        Map<String, Object> data = new HashMap<>();
        data.put("list", pageInfo.getList());
        data.put("pageNum", pageInfo.getPageNum());
        data.put("pageSize", pageInfo.getPageSize());
        data.put("pages", pageInfo.getPages());
        data.put("total", pageInfo.getTotal());
        data.put("isLastPage", pageInfo.isIsLastPage());
        return Result.success(data);
    }
    ///////////////////////////////////////////////////////////////////////////////////////////
//    private void checkTime(Date startTime){
//        Calendar calendar = Calendar.getInstance();
//        calendar.setTime(startTime);
//        int hour = calendar.get(Calendar.HOUR);
//        if(hour ){}
//    }
    /** 医生排班(按日期选医生) */
    private Map<String, Object> doctorTimeListV1(AppointmentAutoMateDto dto){
        SqlSentence sqlSentence = new SqlSentence();
        Map<String, Object> values = new HashMap<>();
        sqlSentence.setM(values);
        values.put("timeType", DoctorTime.TIME_TYPE_WORK);
        values.put("shopId", dto.getShopId());
        values.put("startTime", dto.getStartTime());
        values.put("endTime", dto.getEndTime());
        StringBuilder sql = new StringBuilder();
        sql.append(" select dt.doctorId, e.cnName as doctorName, e.imgUrl ")
                .append(" , date_format(dt.startTime, '%Y-%m-%d') as startTime ")
                .append(" from doctor_time dt ")
                .append(" left join employee e on e.id = dt.doctorId ")
                .append(" where dt.isDel = 0 and dt.timeType = #{m.timeType} and dt.shopId = #{m.shopId} ")
                .append(" and dt.dayTime >= #{m.startTime} and dt.endTime <= #{m.endTime} ")
                .append(" order by dt.dayTime asc ");
        sqlSentence.setSqlSentence(sql.toString());
        List<Map<String, Object>> list = commonService.selectListMap(DoctorTimeMapper.class, sqlSentence);
        if(list == null || list.size() < 1){
            return null;
        }
        //先遍历按日期归类
        List<Map<String, Object>> dataList;
        TreeMap<Object, List<Map<String, Object>>> treeMap = new TreeMap<>();
        for(Map<String, Object> map : list){
            dataList = treeMap.get(map.get("startTime"));
            if(!treeMap.containsKey(map.get("startTime"))){
                dataList = new ArrayList<>();
                treeMap.put(map.get("startTime"), dataList);
            }
            dataList.add(map);
        }
        //然后再组装
        JSONArray arr = new JSONArray();
        JSONObject json;
        for(Map.Entry<Object, List<Map<String, Object>>> entry : treeMap.entrySet()){
            json = new JSONObject();
            json.put("dateTime", entry.getKey());
            json.put("doctorList", entry.getValue());
            arr.add(json);
        }
        json = new JSONObject();
        json.put("list", arr);
        json.put("version", "1");
        return json;
    }
    /** 医生排班(按医生选日期) */
    private Map<String, Object> doctorTimeListV2(AppointmentAutoMateDto dto){
        SqlSentence sqlSentence = new SqlSentence();
        Map<String, Object> values = new HashMap<>();
        sqlSentence.setM(values);
        values.put("shopId", dto.getShopId());
        StringBuilder sql = new StringBuilder();
        //查询门店下的医生员工
        sql.append(" select e.id as doctorId, e.cnName as doctorName, e.imgUrl ")
                .append(" from employee_role r ")
                .append(" join employee e on e.id = r.employeeId ")
                .append(" where r.isDel = 0 and e.isDel = 0 and e.isJob = 1 ")
                .append(" and r.shopId = #{m.shopId} and r.roleUniqueStr = #{m.roleUniqueStr} ");
        sqlSentence.setSqlSentence(sql.toString());
        List<Map<String, Object>> doctorList = commonService.selectListMap(EmployeeMapper.class, sqlSentence);
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("list", doctorList);
        dataMap.put("version", "2");
        if(doctorList == null || doctorList.size() < 1){
            return dataMap;
        }
        //查询门店下对应日期范围的医生排班
        values.put("timeType", DoctorTime.TIME_TYPE_WORK);
        values.put("startTime", dto.getStartTime());
        values.put("endTime", dto.getEndTime());
        sql.setLength(0);
        sql.append(" select dt.doctorId, date_format(dt.startTime, '%Y-%m-%d') as startTime ")
                .append(" from doctor_time dt ")
                .append(" left join employee e on e.id = dt.doctorId ")
                .append(" where dt.isDel = 0 and dt.timeType = #{m.timeType} and dt.shopId = #{m.shopId} ")
                .append(" and dt.dayTime >= #{m.startTime} and dt.endTime <= #{m.endTime} ")
                .append(" order by dt.dayTime asc ");
        sqlSentence.setSqlSentence(sql.toString());
        List<Map<String, Object>> doctorTimeList = commonService.selectListMap(DoctorTimeMapper.class, sqlSentence);
        if(doctorTimeList == null || doctorTimeList.size() < 1){
            return dataMap;
        }
        //按医生id分组归类排班数据
        Map<String, List<Map<String, Object>>> doctorTimeMap = doctorTimeList.stream().collect(Collectors.groupingBy(m->m.get("doctorId").toString()));
        //先遍历按日期归类
        List<Map<String, Object>> dateList;
        for(Map<String, Object> doctorMap : doctorList){
            dateList = doctorTimeMap.get(doctorMap.get("doctorId"));
            if(dateList == null || dateList.size() < 1){
                continue;
            }
            //按时间排序
            dateList.sort(Comparator.comparing((Map<String, Object> h) -> ((String) h.get("startTime"))));
            dataMap.put("dateList", dateList);
        }
        return dataMap;
    }
}
phi_platform_user/src/main/java/com/hx/phip/controller/meiji/MeiJiDataController.java
@@ -2,10 +2,7 @@
import com.alibaba.fastjson.JSONObject;
import com.hx.common.BaseController;
import com.hx.mybatisTool.SqlSentence;
import com.hx.phiappt.common.enums.MeiJiResourceFileEnum;
import com.hx.phiappt.constants.tool.comparePhoto.ComparePhotoUtil;
import com.hx.phiappt.dao.mapper.MjResourceFileMapper;
import com.hx.phiappt.constants.tool.meiji.MeiJiDataTool;
import com.hx.resultTool.Result;
import com.hx.util.StringUtils;
import com.hz.his.dto.meiji.MeiJiDataDto;
@@ -18,7 +15,6 @@
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.*;
/**
 * 美际数据
@@ -41,35 +37,8 @@
            throw new PlatTipsException(PlatformCode.ERROR_PARAMETER_NULL, "美际皮肤报告标识不能为空!");
        }
        SqlSentence sqlSentence = new SqlSentence();
        Map<String, Object> values = new HashMap<>();
        sqlSentence.setM(values);
        values.put("mjSkinReportId", dto.getMjSkinReportId());
        sqlSentence.setSqlSentence(" select fileName, fileUrl from mj_resource_file where isDel = 0 and mjSkinReportId = #{m.mjSkinReportId} ");
        List<Map<String, Object>> list = commonService.selectListMap(MjResourceFileMapper.class, sqlSentence);
        if(list != null && list.size() > 0){
            String flag;
            for(Map<String, Object> map : list){
                //文件验签访问
                map.put("fileUrl", ComparePhotoUtil.getDecryptImagesUrl(sFileService, map.get("fileUrl").toString()));
                //遍历根据文件名转换展示名和排序号
                flag = map.get("fileName").toString();
                flag = flag.toLowerCase(Locale.ROOT);
                for (MeiJiResourceFileEnum meiJiResourceFileEnum : MeiJiResourceFileEnum.values()) {
                    if (Objects.equals(meiJiResourceFileEnum.getFlag(), flag)){
                        map.put("sortNum", meiJiResourceFileEnum.getSortNum());
                        map.put("showName", meiJiResourceFileEnum.getShowName());
                        break;
                    }
                }
            }
            //排序
            list.sort(Comparator.comparing((Map<String, Object> h) -> ((int) h.get("sortNum"))));
        }
        JSONObject data = new JSONObject();
        data.put("list", list);
        data.put("list", MeiJiDataTool.getMjFileList(commonService, sFileService, dto.getMjSkinReportId()));
        return Result.success(data);
    }
phi_platform_user/src/main/java/com/hx/phip/controller/micro/MicroRecordController.java
@@ -9,9 +9,7 @@
import com.hx.common.service.CommonService;
import com.hx.mybatisTool.SqlSentence;
import com.hx.phiappt.common.BaseClassifyConstants;
import com.hx.phiappt.common.enums.MeiJiResourceFileEnum;
import com.hx.phiappt.constants.tool.UserInfoTool;
import com.hx.phiappt.constants.tool.comparePhoto.ComparePhotoUtil;
import com.hx.phiappt.constants.tool.employee.EmployeeTool;
import com.hx.phiappt.constants.tool.meiji.MeiJiDataTool;
import com.hx.phiappt.constants.tool.shop.ShopTool;
@@ -472,29 +470,7 @@
            mjData.remove("contents");
            //查询对应关联资源文件记录
            values.put("mjSkinReportId", mjData.get("id"));
            sqlSentence.setSqlSentence(" select fileName, fileUrl from mj_resource_file where isDel = 0 and mjSkinReportId = #{m.mjSkinReportId} ");
            List<Map<String, Object>> list = commonService.selectListMap(MjResourceFileMapper.class, sqlSentence);
            if(list != null && list.size() > 0){
                String flag;
                for(Map<String, Object> map : list){
                    //文件验签访问
                    map.put("fileUrl", ComparePhotoUtil.getDecryptImagesUrl(sFileService, map.get("fileUrl").toString()));
                    //遍历根据文件名转换展示名和排序号
                    flag = map.get("fileName").toString();
                    flag = flag.toLowerCase(Locale.ROOT);
                    for (MeiJiResourceFileEnum meiJiResourceFileEnum : MeiJiResourceFileEnum.values()) {
                        if (Objects.equals(meiJiResourceFileEnum.getFlag(), flag)){
                            map.put("sortNum", meiJiResourceFileEnum.getSortNum());
                            map.put("showName", meiJiResourceFileEnum.getShowName());
                            break;
                        }
                    }
                }
                //排序
                list.sort(Comparator.comparing((Map<String, Object> h) -> ((int) h.get("sortNum"))));
                mjData.put("rsList", list);
            }
            mjData.put("rsList", MeiJiDataTool.getMjFileList(commonService, sFileService, MapUtil.getString(mjData, "id")));
        }
    }
phi_platform_user/src/main/java/com/hx/phip/controller/micro/MicroRecordV2Controller.java
@@ -9,9 +9,7 @@
import com.hx.exception.TipsException;
import com.hx.mybatisTool.SqlSentence;
import com.hx.phiappt.common.BaseClassifyConstants;
import com.hx.phiappt.common.enums.MeiJiResourceFileEnum;
import com.hx.phiappt.constants.tool.UserInfoTool;
import com.hx.phiappt.constants.tool.comparePhoto.ComparePhotoUtil;
import com.hx.phiappt.constants.tool.employee.EmployeeTool;
import com.hx.phiappt.constants.tool.meiji.MeiJiDataTool;
import com.hx.phiappt.constants.tool.shop.ShopTool;
@@ -679,7 +677,7 @@
            }
            data.put("mjSkinReport",mjSkinReport);
            //查询对应关联资源文件记录
            data.put("rsList",getMjFileList(mjRecordId));
            data.put("rsList", MeiJiDataTool.getMjFileList(commonService, sFileService, mjRecordId));
            //查询治疗方案
            Map<String, List<MicroPlanItem>> microPlanItemMap = new HashMap<>();
@@ -1162,47 +1160,13 @@
        mjData.put("treatPlanItemList", treatPlanItemListMap);
        //查询对应关联资源文件记录
        List<Map<String, Object>> rsList = getMjFileList(mjData.get("id").toString());
        List<Map<String, Object>> rsList = MeiJiDataTool.getMjFileList(commonService, sFileService, mjData.get("id").toString());
        if (rsList != null && rsList.size() > 0){
            mjData.put("rsList", rsList);
        }
        return mjData;
    }
    /**查询美际文件资料*/
    private List<Map<String, Object>> getMjFileList(String id) {
        if (StringUtils.isEmpty(id)){
            return new ArrayList<>();
        }
        Map<String, Object> values = new HashMap<>();
        values.put("mjSkinReportId",id);
        SqlSentence sqlSentence = new SqlSentence();
        sqlSentence.sqlSentence(" SELECT id,fileName,fileUrl FROM mj_resource_file WHERE isDel = 0 AND mjSkinReportId = #{m.mjSkinReportId} ", values);
        List<Map<String, Object>> rsList = commonService.selectListMap(MjResourceFileMapper.class, sqlSentence);
        if (rsList != null && rsList.size() > 0) {
            //美际资源文件标识
            String flag;
            for (Map<String, Object> map : rsList) {
                //文件验签访问
                map.put("fileUrl", ComparePhotoUtil.getDecryptImagesUrl(sFileService, map.get("fileUrl").toString()));
                //遍历根据文件名转换展示名和排序号
                flag = map.get("fileName").toString();
                flag = flag.toLowerCase(Locale.ROOT);
                for (MeiJiResourceFileEnum meiJiResourceFileEnum : MeiJiResourceFileEnum.values()) {
                    if (Objects.equals(meiJiResourceFileEnum.getFlag(), flag)) {
                        map.put("sortNum", meiJiResourceFileEnum.getSortNum());
                        map.put("showName", meiJiResourceFileEnum.getShowName());
                        break;
                    }
                }
            }
            //排序
            rsList.sort(Comparator.comparing((Map<String, Object> h) -> ((int) h.get("sortNum"))));
        }
        return rsList;
    }
    /**
phi_platform_user/src/main/java/com/hx/phip/service/appointment/AppointmentV2Service.java
@@ -3,7 +3,6 @@
import com.hx.phiappt.model.*;
import com.hx.phiappt.vo.OperatorVo;
import java.util.Date;
import java.util.List;
/**
phi_platform_user/src/main/java/com/hx/phip/service/appointment/impl/AppointmentV2ServiceImpl.java
@@ -7,9 +7,10 @@
import com.hx.phiappt.constants.tool.appointment.AppointmentTool;
import com.hx.phiappt.constants.tool.appointment.GuideSyncAppItemUtil;
import com.hx.phiappt.dao.mapper.*;
import com.hx.phiappt.dao.mapper.custom.AppointmentV2Mapper;
import com.hx.phiappt.dao.mapper.AppointmentV2Mapper;
import com.hx.phiappt.model.*;
import com.hx.phiappt.util.AppointmentV2Util;
import com.hx.phiappt.util.system.config.AppointmentConfigUtil;
import com.hx.phiappt.vo.OperatorVo;
import com.hx.phip.service.appointment.AppointmentV2Service;
import com.hx.util.StringUtils;
@@ -459,6 +460,10 @@
            timerHandleItem.setType(TimerHandleItem.TYPE_APP_APPLY);
            timerHandleItem.setCreateTime(appointment.getStartTime());
            commonDao.insert(TimerHandleItemMapper.class, timerHandleItem);
            //处理是否发送预约审核通知
            AppointmentConfigUtil.handleAppointmentAuditNotice(commonDao, appointment);
        }else if(appointment.getStatus() == Appointment.STATUS_SUC){
            //预约成功
            timerHandleItem = new TimerHandleItem();
@@ -531,10 +536,17 @@
            timerHandleItem.setCreateTime(appointment.getStartTime());
            if (appointment.getStatus() == Appointment.STATUS_WAIT) {
                timerHandleItem.setType(TimerHandleItem.TYPE_APP_APPLY);
                //处理是否发送预约审核通知
                AppointmentConfigUtil.handleAppointmentAuditNotice(commonDao, appointment);
            } else if (appointment.getStatus() == Appointment.STATUS_SUC) {
                timerHandleItem.setType(TimerHandleItem.TYPE_APP_SUC);
                //新增同步导医处理
                GuideSyncAppItemUtil.syncApp(commonService, appointment.getId());
            }
            commonDao.insert(TimerHandleItemMapper.class, timerHandleItem);
        }
    }