陈昶聿
2026-07-29 1f66eb9a6353d638f5b9cb33b934bd4705e4efed
smartor/src/main/java/com/smartor/common/ScheduleSubtaskBuilder.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,192 @@
package com.smartor.common;
import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.DateUtils;
import com.smartor.domain.*;
import com.smartor.mapper.ServiceSubtaskMapper;
import com.smartor.mapper.ServiceSubtaskPreachformMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
 * ä»»åŠ¡ç»„ï¼ˆappltype=5)subtask ç”Ÿæˆå™¨
 * <p>
 * å•一职责:根据 schedule + detailList ä¸ºæ¯ä¸ªæ‚£è€…派生 subtask。
 * åŒæ—¶æœåŠ¡ä¸¤æ¡è·¯å¾„ï¼š
 * (a) å‰ç«¯æ‰‹åŠ¨å‹¾é€‰æ‚£è€…ï¼ˆinsertOrUpdateTask) â€”— æ—§ 6 å‚入口;
 * (b) HIS è‡ªåŠ¨çº³å…¥æ–°å‡ºé™¢æ‚£è€…ï¼ˆPatMedInhospServiceImpl.writeInSubTask) â€”— æ–° 5 å‚入口。
 * ä¸¤æ¡è·¯å¾„统一从 baseSubtask ä¸Šå–基准日字段,避免生成器与 PatTaskRelevance/ServiceTaskVO è€¦åˆã€‚
 *
 * @author smartor
 * @date 2026-06-30
 */
@Slf4j
@Component
public class ScheduleSubtaskBuilder {
    @Autowired
    private ServiceSubtaskMapper serviceSubtaskMapper;
    @Autowired
    private ServiceSubtaskPreachformMapper serviceSubtaskPreachformMapper;
    /**
     * ä¸ºå•个患者派生 subtask(appltype=5)—— è§£è€¦å…¥å£ï¼ˆè‡ªåŠ¨çº³å…¥ & æ‰‹åŠ¨å‹¾é€‰ç»Ÿä¸€èµ°è¿™é‡Œï¼‰ã€‚
     * <p>
     * éžå¾ªçŽ¯ï¼šæŒ‰ detailList ä¸€æ¬¡æ€§é“ºå¹³ N æ¡ï¼›
     * å¾ªçޝ  ï¼šæŒ‰ schedule.currentLoopCount ç”Ÿæˆå½“前轮 N æ¡ï¼ŒåŽç»­è½®æ¬¡ç”±è°ƒåº¦å™¨æ»šåŠ¨å»ºã€‚
     *
     * @param serviceTask     ä¸»ä»»åŠ¡ï¼ˆå·²è½åº“ï¼‰
     * @param schedule        å·²è½åº“的主计划
     * @param detailList      æ˜Žç»†åˆ—表(按 seq å‡åºï¼‰
     * @param baseSubtask     æ¨¡æ¿ subtask(已填充患者基础信息 + åŸºå‡†æ—¥å­—段),方法内会深拷贝
     * @param preachformList  å‘送方式(调用方已解析好,可为空)
     */
    public void buildSubtasksForPatient(ServiceTask serviceTask,
                                        ServiceTaskSchedule schedule,
                                        List<ServiceTaskScheduleDetail> detailList,
                                        ServiceSubtask baseSubtask,
                                        List<Map<String, Object>> preachformList) {
        if (CollectionUtils.isEmpty(detailList)) {
            throw new BaseException("任务组明细为空,无法生成 subtask, taskid=" + serviceTask.getTaskid());
        }
        Date benchmark = resolveBenchmark(schedule, baseSubtask);
        long currentLoop = schedule.getCurrentLoopCount() == null ? 0L : schedule.getCurrentLoopCount();
        for (ServiceTaskScheduleDetail detail : detailList) {
            ServiceSubtask subtask = copyFromBase(baseSubtask);
            // å›žæº¯å­—段
            subtask.setScheduleId(schedule.getId());
            subtask.setScheduleDetailId(detail.getId());
            subtask.setScheduleSeq(detail.getSeq());
            subtask.setLoopCount(currentLoop);
            // æ¨¡æ¿ï¼šdetail ä¼˜å…ˆäºŽ task
            if (detail.getTemplateid() != null) {
                subtask.setTemplateid(detail.getTemplateid());
                subtask.setTemplatename(detail.getTemplatename());
            }
            if (detail.getLibtemplateid() != null) {
                subtask.setLibtemplateid(detail.getLibtemplateid());
            }
            // æ—¶é—´ï¼šåŸºå‡†æ—¥ + dayOffset
            Date visitTime = addDays(benchmark, detail.getDayOffset());
            subtask.setVisitTime(visitTime);
            subtask.setSenddate(visitTime);
            subtask.setLongSendTime(visitTime);
            // çŠ¶æ€ï¼šä¸ŽåŽŸæµç¨‹ä¸€è‡´ï¼Œæ–°å»ºåŽç½®ä¸ºå¾…å‘é€
            subtask.setSendstate(2L);
            subtask.setCreateTime(DateUtils.getNowDate());
            subtask.setUpdateTime(DateUtils.getNowDate());
            serviceSubtaskMapper.insertServiceSubtask(subtask);
            insertPreachform(serviceTask, preachformList, subtask);
            log.info("[任务组] taskid={} patid={} ç”Ÿæˆ subtask id={} seq={} dayOffset={} visitTime={}",
                    serviceTask.getTaskid(), baseSubtask.getPatid(),
                    subtask.getId(), detail.getSeq(), detail.getDayOffset(), visitTime);
        }
    }
    /**
     * å…¼å®¹å…¥å£ï¼šå‰ç«¯æ‰‹åŠ¨å‹¾é€‰æ‚£è€…ï¼ˆinsertOrUpdateTask)。
     * æŠŠ patTaskRelevance çš„基准日字段回填到 baseSubtask åŽï¼Œå§”托给解耦入口。
     */
    public void buildSubtasksForPatient(ServiceTask serviceTask,
                                        List<Map<String, Object>> preachformList,
                                        ServiceTaskSchedule schedule,
                                        List<ServiceTaskScheduleDetail> scheduleDetailList,
                                        PatTaskRelevance patTaskRelevance,
                                        ServiceSubtask baseSubtask) {
        // å›žå¡«åŸºå‡†æ—¥å­—段(手动路径的 baseSubtask ç”± VO æ‹¼è£…,基准日字段可能未填全)
        if (baseSubtask.getStarttime() == null) {
            baseSubtask.setStarttime(patTaskRelevance.getInhosptime() != null
                    ? patTaskRelevance.getInhosptime() : patTaskRelevance.getStarttime());
        }
        if (baseSubtask.getEndtime() == null) {
            baseSubtask.setEndtime(patTaskRelevance.getEndtime());
        }
        if (baseSubtask.getAdmindate() == null) {
            baseSubtask.setAdmindate(patTaskRelevance.getVisittime());
        }
        buildSubtasksForPatient(serviceTask, schedule, scheduleDetailList, baseSubtask, preachformList);
    }
    /**
     * æ ¹æ® scheduleBenchmark è§£æžåŸºå‡†æ—¶é—´ï¼š
     * 0-自定义时间 1-入院时间 2-出院时间 3-就诊时间 4-入组时间
     * å…¨éƒ¨ä»Ž baseSubtask å–,取不到兜底当前时间。
     */
    private Date resolveBenchmark(ServiceTaskSchedule schedule, ServiceSubtask base) {
        Integer benchmark = schedule.getScheduleBenchmark() == null ? 0 : schedule.getScheduleBenchmark();
        Date now = DateUtils.getNowDate();
        switch (benchmark) {
            case 1:
                return base.getStarttime() != null ? base.getStarttime() : now;
            case 2:
                return base.getEndtime() != null ? base.getEndtime() : now;
            case 3:
                return base.getAdmindate() != null ? base.getAdmindate() : now;
            case 4:
                return base.getCreateTime() != null ? base.getCreateTime() : now;
            case 0:
            default:
                return schedule.getScheduleBenchmarkCustomTime() != null
                        ? schedule.getScheduleBenchmarkCustomTime() : now;
        }
    }
    private Date addDays(Date base, int dayOffset) {
        Calendar c = Calendar.getInstance();
        c.setTime(base);
        c.add(Calendar.DAY_OF_MONTH, dayOffset);
        return c.getTime();
    }
    /**
     * å†™ service_subtask_preachform,发送方式由调用方备好。
     */
    private void insertPreachform(ServiceTask serviceTask, List<Map<String, Object>> pfList, ServiceSubtask subtask) {
        if (CollectionUtils.isEmpty(pfList)) {
            return;
        }
        for (Map<String, Object> map : pfList) {
            ServiceSubtaskPreachform pf = new ServiceSubtaskPreachform();
            pf.setSort(ObjectUtils.isEmpty(map.get("sort")) ? 0 : Long.valueOf(map.get("sort").toString()));
            pf.setPreachform(ObjectUtils.isEmpty(map.get("preachform")) ? "" : map.get("preachform").toString());
            pf.setCompensateTime(ObjectUtils.isEmpty(map.get("compensateTime")) ? "" : map.get("compensateTime").toString());
            pf.setTaskid(serviceTask.getTaskid());
            pf.setSubid(subtask.getId());
            pf.setSendstate("1");
            pf.setOrgid(serviceTask.getOrgid());
            pf.setCreateTime(new Date());
            serviceSubtaskPreachformMapper.insertServiceSubtaskPreachform(pf);
        }
    }
    /**
     * æ·±æ‹·è´ baseSubtask åˆ°ä¸€ä¸ªæ–°å¯¹è±¡ï¼ˆæ¯æ¬¡ insert åŽ id ä¼šå›žå†™ï¼Œå¿…须独立实例)。
     * ç”¨ fastjson åšæ·±æ‹·è´ï¼Œçœä¸€å † set。
     */
    private ServiceSubtask copyFromBase(ServiceSubtask base) {
        String json = JSON.toJSONString(base);
        ServiceSubtask copy = JSON.parseObject(json, ServiceSubtask.class);
        // ä¸»é”®ã€id å¿…须清掉,否则 useGeneratedKeys ä»ä¼šç”¨ä¸Šè½®çš„ id è§¦å‘主键冲突
        copy.setId(null);
        return copy;
    }
}