package com.ruoyi.task.controller;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.ISelect;
import com.ruoyi.common.annotation.AddOrgId;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.entity.SysUserDept;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.PreachFormEnum;
import com.ruoyi.common.enums.SendStateEnum;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.reflect.ReflectUtils;
import com.ruoyi.common.core.service.TaskOpsTriggerApi;
import com.ruoyi.task.api.spi.TaskSysConfigPort;
import com.ruoyi.task.api.spi.TaskSysUserDeptPort;
import com.ruoyi.satisfaction.api.SatisfactionExportBundle;
import com.ruoyi.satisfaction.api.SatisfactionFacade;
import com.ruoyi.task.api.spi.TaskSubtaskRecordPort;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import com.ruoyi.template.domain.VO.HeLibraryCountVO;
import static com.ruoyi.common.utils.SecurityUtils.getLoginUser;
import com.ruoyi.task.domain.entity.ServiceSubtaskEntity;
import com.ruoyi.task.domain.ServiceStatisticsRequest;
import com.ruoyi.task.domain.ServiceStatisticsResponse;
import com.ruoyi.task.domain.ServiceSubtask;
import com.ruoyi.task.domain.ServiceSubtaskCountReq;
import com.ruoyi.task.domain.ServiceSubtaskRecord;
import com.ruoyi.task.domain.ServiceSubtaskStatistic;
import com.ruoyi.task.domain.ServiceTask;
import com.ruoyi.task.domain.VO.ServiceSubtaskCotinueCountVO;
import com.ruoyi.task.service.IServiceSubtaskService;
import com.ruoyi.task.service.IServiceTaskService;
import com.ruoyi.task.domain.PatArchiveSrmVO;
import com.ruoyi.task.domain.ServiceSubTaskDetailReq;
import com.ruoyi.task.domain.ServiceSubtaskDiagname;
import com.ruoyi.task.domain.ServiceSubtaskRes;
import com.ruoyi.task.domain.ServiceSubtaskTemplateVO;
import com.ruoyi.task.domain.ServiceTaskVO;
import com.ruoyi.task.domain.VO.ServiceSubtaskVO;
import com.ruoyi.task.domain.VO.TransferDeptVO;
import com.ruoyi.task.domain.ServiceSubtaskExport;
/**
* 单一任务(随访)Controller
*
* ⚠️ 电话相关的 6 个端点(phoneCallBack / phoneCallBackYQ / taskPull /
* saveQuestionAnswerPhone / recordAcceptshanghai / recordAccept)已随电话模块化
* 整体搬进 {@code ruoyi-phone} 的 {@code PhoneCallbackController},URL 保持不变
* (外部电话平台的回调地址不能改),因此本 Controller 与电话模块共用
* {@code /smartor/serviceSubtask} 这一前缀,只要完整路径不重复即可正常注册。
*
* @author ruoyi
* @date 2024-02-02
*/
@Slf4j
@Api(description = "单一任务(随访宣教)")
@RestController
@RequestMapping("/smartor/serviceSubtask")
public class ServiceSubtaskController extends BaseController {
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setAutoGrowCollectionLimit(1024); // 或 2048、4096 等
}
@Autowired
private IServiceSubtaskService serviceSubtaskService;
/**
* 满意度模块对外门面(常驻 Bean)。
*
* 满意度相关数据(问题详情占比)只能通过它获取;满意度模块关闭时
* 门面返回空结果并打 WARN,不会影响随访导出的其它内容。
*/
@Autowired
private SatisfactionFacade satisfactionFacade;
@Autowired
private IServiceTaskService serviceTaskService;
@Autowired
private TaskSysUserDeptPort taskSysUserDeptPort;
@Autowired
private TaskSubtaskRecordPort serviceSubtaskRecordService;
@Autowired
private TaskSysConfigPort taskSysConfigPort;
/**
* 任务运维触发能力。
*
* 原先此处直接注入 {@code ruoyi-quartz} 的 {@code RyTask} / {@code ICollectHISService},
* 会让「端点归属」与「HIS 采集实现」绑死:这 6 个端点的归属要搬进 {@code ruoyi-task},
* 而实现({@code RyTask} 2214 行、注入约 20 个 smartor service)不能搬,
* 否则形成 {@code ruoyi-task -> smartor} + {@code ruoyi-quartz -> ruoyi-task} 的硬循环。
*
* 改为经 {@code ruoyi-common} 的端口取用:接口在 ruoyi-common,
* 实现({@code TaskOpsTriggerApiImpl})留在 ruoyi-quartz。
* 这样端点可以整体搬走而不需要依赖 ruoyi-quartz。
*/
@Autowired
private TaskOpsTriggerApi taskOpsTriggerApi;
@Value("${spring.profiles.active}")
private String active;
@Value("${localIP}")
private String localIP;
@Value("${req_path}")
private String req_path;
@Value("${isAdmin}")
private List isAdmin;
@Autowired
private RedisCache redisCache;
/**
* 转移科室病区
*/
@ApiOperation("转移科室病区")
@PostMapping("/transferDept")
public Map transferDept(@RequestBody TransferDeptVO transferDeptVO) {
Integer i = serviceSubtaskService.transferDept(transferDeptVO);
return success(i == 1 ? true : false);
}
/**
* 查询患者随访信息
*/
@ApiOperation("查询患者随访信息")
@PostMapping("/patItem")
public Map patItem(@RequestBody ServiceSubtaskVO serviceSubtaskVO) {
serviceSubtaskVO.setPageNum(PageUtils.getOffset(serviceSubtaskVO.getPageNum(), serviceSubtaskVO.getPageSize()));
List serviceSubtaskList = null;
LoginUser loginUser = getLoginUser();
SysUser user = loginUser.getUser();
serviceSubtaskVO.setOrgid(user.getOrgid());
serviceSubtaskVO.setCampusid(user.getCampusid());
ServiceSubtaskEntity serviceSubtaskEntity = null;
if (serviceSubtaskVO != null) {
serviceSubtaskEntity = DtoConversionUtils.sourceToTarget(serviceSubtaskVO, ServiceSubtaskEntity.class);
serviceSubtaskEntity.setContinueContent(ObjectUtils.isNotEmpty(serviceSubtaskVO.getContinueContent()) ? serviceSubtaskVO.getContinueContent().toString() : null);
serviceSubtaskList = serviceSubtaskService.patItem(serviceSubtaskEntity);
}
// 批量查 subtask_record,1次SQL替代循环中N次单独查
List subtaskIds = serviceSubtaskList.stream().map(ServiceSubtaskRes::getId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList());
Map> recordMap = serviceSubtaskRecordService.selectRecordMapBySubtaskIds(subtaskIds);
for (ServiceSubtaskRes serviceSubtask : serviceSubtaskList) {
serviceSubtask.setServiceSubtaskRecordList(recordMap.getOrDefault(serviceSubtask.getId(), new ArrayList<>()));
}
// patItemCount 走Redis缓存版,避免每次全表聚合扫描
Map map = getPatItemCountWithCache(serviceSubtaskEntity);
map.put("serviceSubtaskList", serviceSubtaskList);
List