فهرست منبع

销售后台增加跟进会员接口+已处理任务+待处理任务

cgp 1 هفته پیش
والد
کامیت
023963f10c

+ 121 - 5
fs-company/src/main/java/com/fs/company/controller/qw/FsDoctorMemberSalesController.java

@@ -2,21 +2,37 @@ package com.fs.company.controller.qw;
 
 
 import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.utils.ServletUtils;
 import com.fs.company.domain.CompanyUser;
+import com.fs.company.mapper.CompanyUserRoleMapper;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
+import com.fs.his.domain.FsSopDoctorTask;
+import com.fs.his.domain.FsStoreOrder;
+import com.fs.his.dto.FsDoctorTaskDTO;
+import com.fs.his.dto.SopDoctorTaskDto;
+import com.fs.his.service.IFsSopDoctorTaskService;
+import com.fs.his.service.IFsStoreOrderService;
+import com.fs.his.vo.SopDoctorTaskVo;
+import com.fs.hisStore.service.IFsUserInformationCollectionService;
+import com.fs.hisStore.vo.FsUserInformationCollectionVO;
+import com.fs.qw.param.FsDoctorMemberSalesQueryParam;
 import com.fs.qw.param.MemberSalesParam;
 import com.fs.qw.service.IFsDoctorMemberSalesService;
+import com.fs.qw.vo.FsDoctorMemberSalesVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Collections;
+import java.util.List;
 
 /**
  * 医生会员搭销控制层
@@ -29,9 +45,24 @@ public class FsDoctorMemberSalesController extends BaseController {
     @Autowired
     private IFsDoctorMemberSalesService doctorMemberSalesService;
 
+    @Autowired
+    private IFsSopDoctorTaskService fsSopDoctorTaskService;
+
     @Autowired
     private TokenService tokenService;
 
+    @Autowired
+    private CompanyUserRoleMapper roleMapper;
+
+    @Autowired
+    private IFsStoreOrderService fsStoreOrderService;
+
+    @Autowired
+    private IFsStoreOrderService orderService;
+
+    @Autowired
+    private IFsUserInformationCollectionService userInfoCollectionService;
+
 
     //@PreAuthorize("@ss.hasPermi('qw:memberSales:push')")
     @PostMapping("/push")
@@ -43,4 +74,89 @@ public class FsDoctorMemberSalesController extends BaseController {
 
         return doctorMemberSalesService.push(param);
     }
+
+    //@PreAuthorize("@ss.hasPermi('qw:companyUserFollowUpMembers:list')")
+    @GetMapping("/companyUserFollowUpMembers")
+    public R selectCompanyUserMemberSalesVOList(FsDoctorMemberSalesQueryParam param){
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyUserId(loginUser.getUser().getUserId());
+        //管理员查看所有数据
+        Long isAdmin = roleMapper.companyUserIsAdmin(param.getCompanyUserId());
+        if (isAdmin != null) {
+            param.setCompanyUserId(null);
+        }
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        List<FsDoctorMemberSalesVO> voList = doctorMemberSalesService.selectFsDoctorMemberSalesVOList(param);
+        PageInfo<FsDoctorMemberSalesVO> listPageInfo=new PageInfo<>(voList);
+        return R.ok().put("data", listPageInfo);
+    }
+
+    /**
+     * 查询跟进会员任务处理记录
+     * @param queryDto 医生处理任务
+     * @return 医生处理sop任务集合
+     * */
+    @GetMapping("/selectCompanyUserTaskVoListHandleRecords")
+    public TableDataInfo selectCompanyUserTaskVoListHandleRecords(SopDoctorTaskDto queryDto)
+    {
+        startPage();
+        List<SopDoctorTaskVo> list = fsSopDoctorTaskService.selectFsSopDoctorTaskVoListHandleRecords(queryDto);
+        return getDataTable(list);
+
+    }
+    /**
+     * 查询用户历史订单列表
+     * */
+    @GetMapping("/storeOrder/userHistoryOrderList")
+    public TableDataInfo userHistoryOrderList(FsStoreOrder fsStoreOrder)
+    {
+        startPage();
+        fsStoreOrder.setCompanyUserId(fsStoreOrder.getCompanyUserId());
+        List<FsStoreOrder> list = fsStoreOrderService.selectFsStoreOrderList(fsStoreOrder);
+        if (CollectionUtils.isEmpty(list)){
+            return getDataTable(Collections.emptyList());
+        }
+        return getDataTable(list);
+
+    }
+    @GetMapping("/taskList")
+    public R selectFsDoctorMemberSalesVOList(FsSopDoctorTask param){
+        startPage();
+        List<FsSopDoctorTask> taskList = fsSopDoctorTaskService.selectFsSopDoctorTaskList(param);
+        PageInfo<FsSopDoctorTask> listPageInfo=new PageInfo<>(taskList);
+        return R.ok().put("data", listPageInfo);
+    }
+    /**
+     *
+     * 提交跟进会员任务
+     * */
+    @PutMapping("/submitCompanyTask")
+    public R submitDoctorTask(@RequestBody FsDoctorTaskDTO addTaskDto){
+        //当前登录销售id
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        addTaskDto.setCompanyUserId(loginUser.getUser().getUserId());
+        addTaskDto.setHandlePersonType(2);//2:销售人员处理
+        int update = fsSopDoctorTaskService.submitDoctorTask(addTaskDto);
+        if (update>0){
+            return R.ok();
+        }
+        return R.error("提交失败");
+    }
+
+    @ApiOperation("获取用户未签收的订单数据")
+    @GetMapping("/getNoReceiveOrderList/{userId}")
+    public R getNoReceiveOrderList(@PathVariable("userId") Long userId) {
+        if(userId==null||userId==0){
+            return R.error("用户id错误");
+        }
+        List<FsStoreOrder> noReceiveOrderList = orderService.selectNoReceiveOrderList(userId);
+        return R.ok().put("data",noReceiveOrderList);
+    }
+
+    //用户采集信息详情
+    @GetMapping("/getCollectionByUserId/{userId}")
+    public R getCollectionByUserId(@PathVariable("userId") Long userId){
+        FsUserInformationCollectionVO detail = userInfoCollectionService.getCollectionByUserId(userId);
+        return R.ok().put("data", detail);
+    }
 }

+ 1 - 1
fs-doctor-app/src/main/java/com/fs/app/controller/FsSopDoctorTaskController.java

@@ -107,7 +107,7 @@ public class FsSopDoctorTaskController extends BaseController
     @GetMapping(value = "/{id}")
     public AjaxResult getInfo(@PathVariable("id") Long id)
     {
-        return AjaxResult.success(fsSopDoctorTaskService.selectFsSopDoctorTaskById(id));
+        return AjaxResult.success(fsSopDoctorTaskService.selectFsSopDoctorTaskVoById(id));
     }
 
     /**

+ 6 - 0
fs-service/src/main/java/com/fs/his/domain/FsSopDoctorTask.java

@@ -58,4 +58,10 @@ public class FsSopDoctorTask extends BaseEntity{
 
     /** 提醒天数 */
     private Integer sendDays;
+
+    /** 处理人类型 2:销售 */
+    private Integer handlePersonType;
+
+    /** 版本 */
+    private Integer version;
 }

+ 2 - 0
fs-service/src/main/java/com/fs/his/dto/FsDoctorTaskDTO.java

@@ -22,4 +22,6 @@ public class FsDoctorTaskDTO {
     private Long exId;
     //医生会员搭销id
     private Long doctorMemberSalesId;
+    /** 处理人类型 2:销售 */
+    private Integer handlePersonType;
 }

+ 6 - 0
fs-service/src/main/java/com/fs/his/dto/SopDoctorTaskDto.java

@@ -46,4 +46,10 @@ public class SopDoctorTaskDto  extends BaseEntity {
 
     /** 1:小品未购 主品未购 2:小品已购 主品未购 3:小品未购 主品已购 4:小品已购 主品已购 */
     private Integer type;
+
+    /** 版本号 */
+    private Integer version;
+
+    /** 处理人类型 暂定2是销售*/
+    private Integer handlePersonType;
 }

+ 4 - 1
fs-service/src/main/java/com/fs/his/mapper/FsSopDoctorTaskMapper.java

@@ -21,7 +21,10 @@ public interface FsSopDoctorTaskMapper extends BaseMapper<FsSopDoctorTask>{
      * @param id 医生处理sop任务主键
      * @return 医生处理sop任务
      */
-    SopDoctorTaskVo selectFsSopDoctorTaskById(Long id);
+    SopDoctorTaskVo selectFsSopDoctorTaskVoById(Long id);
+
+
+    FsSopDoctorTask selectFsSopDoctorTaskById(Long id);
 
     /**
      * 查询医生处理sop任务列表

+ 1 - 1
fs-service/src/main/java/com/fs/his/service/IFsSopDoctorTaskService.java

@@ -20,7 +20,7 @@ public interface IFsSopDoctorTaskService extends IService<FsSopDoctorTask>{
      * @param id 医生处理sop任务主键
      * @return 医生处理sop任务
      */
-    SopDoctorTaskVo selectFsSopDoctorTaskById(Long id);
+    SopDoctorTaskVo selectFsSopDoctorTaskVoById(Long id);
 
     /**
      * 查询医生处理sop任务列表

+ 19 - 4
fs-service/src/main/java/com/fs/his/service/impl/FsSopDoctorTaskServiceImpl.java

@@ -61,9 +61,9 @@ public class FsSopDoctorTaskServiceImpl extends ServiceImpl<FsSopDoctorTaskMappe
      * @return 医生处理sop任务
      */
     @Override
-    public SopDoctorTaskVo selectFsSopDoctorTaskById(Long id)
+    public SopDoctorTaskVo selectFsSopDoctorTaskVoById(Long id)
     {
-        SopDoctorTaskVo sopDoctorTaskVo = fsSopDoctorTaskMapper.selectFsSopDoctorTaskById(id);
+        SopDoctorTaskVo sopDoctorTaskVo = fsSopDoctorTaskMapper.selectFsSopDoctorTaskVoById(id);
         //医生端查看客户手机号直接解密
         if (sopDoctorTaskVo!=null&&sopDoctorTaskVo.getPhone()!=null&&sopDoctorTaskVo.getPhone().length()>11){
             sopDoctorTaskVo.setPhone(decryptPhone(sopDoctorTaskVo.getPhone()));
@@ -174,9 +174,19 @@ public class FsSopDoctorTaskServiceImpl extends ServiceImpl<FsSopDoctorTaskMappe
             log.error("会员搭销数据不存在,doctorMemberSalesId:{}", addTaskDto.getDoctorMemberSalesId());
             throw new CustomException("会员搭销ID不存在");
         }
+        FsSopDoctorTask existingTask = fsSopDoctorTaskMapper.selectFsSopDoctorTaskById(addTaskDto.getId());
+        if (existingTask == null) {
+            throw new CustomException("任务不存在,无法处理");
+        }
+        if (existingTask.getStatus() != null && existingTask.getStatus() == 1) {
+            // 如果任务已经是已处理状态,直接抛出异常
+            throw new CustomException("该任务已被处理,无法重复提交");
+        }
+        Integer currentVersion = existingTask.getVersion();
         // --- 2. 更新主任务表 ---
         FsSopDoctorTask doctorTask = new FsSopDoctorTask();
         doctorTask.setId(addTaskDto.getId());
+        doctorTask.setVersion(currentVersion); //设置旧版本号,用于乐观锁 WHERE 条件
         doctorTask.setDoctorId(addTaskDto.getDoctorId());
         doctorTask.setStatus(1); // 0:待处理,1:已处理
         doctorTask.setUserId(fsDoctorMemberSales.getFsUserId()); // 会员id
@@ -184,7 +194,7 @@ public class FsSopDoctorTaskServiceImpl extends ServiceImpl<FsSopDoctorTaskMappe
         doctorTask.setRemark(addTaskDto.getRemark());
         doctorTask.setUpdateTime(DateUtils.getNowDate());
         doctorTask.setSendDays(addTaskDto.getSendDays());
-
+        doctorTask.setHandlePersonType(addTaskDto.getHandlePersonType());//操作人员类型2:销售
 
         //如果是"签收"类型 额外处理
         if (addTaskDto.getHandleType() != null && addTaskDto.getHandleType() == 1) {
@@ -203,7 +213,11 @@ public class FsSopDoctorTaskServiceImpl extends ServiceImpl<FsSopDoctorTaskMappe
         }
         //更新task状态
         int updateResult = fsSopDoctorTaskMapper.updateFsSopDoctorTask(doctorTask);
-
+        if (updateResult == 0) {
+            // 更新影响行数为0,说明乐观锁生效,数据已被其他线程修改
+            log.warn("提交任务时发生冲突,任务ID: {}, 原始版本号: {}", addTaskDto.getId(), currentVersion);
+            throw new CustomException("该任务已被他人处理,请刷新后重试");
+        }
         // --- 3. "提醒时间"类型执行后续操作 ---
         if (addTaskDto.getHandleType() != null && addTaskDto.getHandleType() == 2) {
             // --- 3.1 计算提醒时间 ---
@@ -250,6 +264,7 @@ public class FsSopDoctorTaskServiceImpl extends ServiceImpl<FsSopDoctorTaskMappe
         if (baseDate == null || daysToAdd == null || daysToAdd <= 0) {
             throw new CustomException("基准日期和增加天数都不能为空且天数需大于0");
         }
+
         // 1. 将 Date 转换为 Instant,再转换为 LocalDate (忽略时区影响,只取日期部分)
         LocalDate localDate = baseDate.toInstant()
                 .atZone(ZoneId.systemDefault()) // 使用系统默认时区进行转换

+ 6 - 0
fs-service/src/main/java/com/fs/his/vo/SopDoctorTaskVo.java

@@ -74,6 +74,12 @@ public class SopDoctorTaskVo {
     /** 提醒天数 */
     private Integer sendDays;
 
+    /** 处理人类型 2:销售 */
+    private Integer handlePersonType;
+
+    /** 版本号 */
+    private Integer version;
+
     //医生会员搭销id
     private Long doctorMemberSalesId;
 }

+ 7 - 0
fs-service/src/main/java/com/fs/qw/param/FsDoctorMemberSalesQueryParam.java

@@ -12,11 +12,18 @@ public class FsDoctorMemberSalesQueryParam extends BaseParam implements Serializ
 
     private Long doctorId;
 
+    private Long companyUserId;
+
     private String userName;
     /**
      * 销售姓名
      */
     private String companyUserName;
+
+    /**
+     * 医生姓名
+     */
+    private String doctorName;
     /**
      * 客户真实姓名
      */

+ 5 - 0
fs-service/src/main/java/com/fs/qw/vo/FsDoctorMemberSalesVO.java

@@ -24,6 +24,11 @@ public class FsDoctorMemberSalesVO {
      */
     private String companyUserName;
 
+    /**
+     * 医生名称
+     */
+    private String doctorName;
+
     /** 销售公司 */
     private Long companyId;
 

+ 24 - 5
fs-service/src/main/resources/mapper/his/FsSopDoctorTaskMapper.xml

@@ -19,6 +19,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="qwExternalContactId"    column="qw_external_contact_id"    />
         <result property="handleType"    column="handle_type"    />
         <result property="doctorMemberSalesId"    column="doctor_member_sales_id"    />
+        <result property="handlePersonType"    column="handle_person_type"    />
+        <result property="version"    column="version"    />
     </resultMap>
 
     <resultMap type="com.fs.his.vo.SopDoctorTaskVo" id="SopDoctorTaskVoResult">
@@ -38,6 +40,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="handleType"    column="handle_type"    />
         <result property="doctorMemberSalesId"    column="doctor_member_sales_id"    />
         <result property="sendDays"    column="send_days"    />
+        <result property="handlePersonType"    column="handle_person_type"    />
+        <result property="version"    column="version"    />
         <!-- 关联表字段 -->
         <result property="name"     column="name" />          <!-- qwec.name -->
         <result property="companyUserName"   column="company_user_name" />   <!-- cp.nick_name -->
@@ -48,7 +52,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
 
     <sql id="selectFsSopDoctorTaskVo">
-        select id, company_user_id,doctor_id, user_id, status, create_time, update_time, remark, package_id, order_code, type,qw_external_contact_id,handle_type,doctor_member_sales_id,send_days from fs_sop_doctor_task
+        select id, company_user_id,doctor_id, user_id, status, create_time, update_time, remark, package_id, order_code, type,qw_external_contact_id,handle_type,doctor_member_sales_id,send_days,handle_person_type,version from fs_sop_doctor_task
     </sql>
 
     <select id="selectFsSopDoctorTaskVoList" parameterType="com.fs.his.dto.SopDoctorTaskDto" resultMap="SopDoctorTaskVoResult">
@@ -69,7 +73,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         fd.doctor_name,
         sdt.qw_external_contact_id,
         sdt.handle_type,
-        sdt.send_days
+        sdt.send_days,
+        sdt.version,
+        sdt.handle_person_type
         FROM
         fs_sop_doctor_task sdt
         LEFT JOIN company_user cp ON sdt.company_user_id = cp.user_id
@@ -87,6 +93,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="handleType != null "> and sdt.handle_type = #{handleType}</if>
             <if test="doctorMemberSalesId != null "> and sdt.doctor_member_sales_id = #{doctorMemberSalesId}</if>
             <if test="type != null "> and sdt.type = #{type}</if>
+            <if test="version != null "> and sdt.version = #{version}</if>
+            <if test="handlePersonType != null "> and sdt.handle_person_type = #{handlePersonType}</if>
             <if test="qwUserId != null "> and qwec.qw_user_id = #{qwUserId}</if>
             <if test="name != null "> and qwec.name like concat('%', #{name}, '%')</if>
             <if test="companyUserName != null and companyUserName !='' "> and cp.nick_name like concat('%', #{companyUserName}, '%')</if>
@@ -101,7 +109,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         ORDER BY sdt.id DESC
     </select>
     
-    <select id="selectFsSopDoctorTaskById" parameterType="Long" resultMap="SopDoctorTaskVoResult">
+    <select id="selectFsSopDoctorTaskVoById" parameterType="Long" resultMap="SopDoctorTaskVoResult">
         SELECT
             sdt.id,
             sdt.user_id,
@@ -119,7 +127,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             sdt.qw_external_contact_id,
             sdt.handle_type,
             sdt.doctor_member_sales_id,
-            sdt.send_days
+            sdt.send_days,
+            sdt.version,
+            sdt.handle_person_type
         FROM
             fs_sop_doctor_task sdt
                 LEFT JOIN company_user cp ON sdt.company_user_id = cp.user_id
@@ -145,6 +155,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="qwExternalContactId != null">qw_external_contact_id,</if>
             <if test="doctorMemberSalesId != null">doctor_member_sales_id,</if>
             <if test="sendDays != null">send_days,</if>
+            <if test="handlePersonType != null">handle_person_type,</if>
+            <if test="version != null">version,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="companyUserId != null">#{companyUserId},</if>
@@ -161,6 +173,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="qwExternalContactId != null">#{qwExternalContactId},</if>
             <if test="doctorMemberSalesId != null">#{doctorMemberSalesId},</if>
             <if test="sendDays != null">#{sendDays},</if>
+            <if test="handlePersonType != null">#{handlePersonType},</if>
+            <if test="version != null">#{version},</if>
          </trim>
     </insert>
 
@@ -180,8 +194,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="handleType != null">handle_type = #{handleType},</if>
             <if test="qwExternalContactId != null">qw_external_contact_id=#{qwExternalContactId},</if>
             <if test="sendDays != null">send_days=#{sendDays},</if>
+            <if test="handlePersonType != null">handle_person_type=#{handlePersonType},</if>
+            version = version + 1,
         </trim>
-        where id = #{id}
+        where id = #{id} AND version = #{version}
     </update>
 
     <delete id="deleteFsSopDoctorTaskById" parameterType="Long">
@@ -201,4 +217,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <if test="status != null "> and status = #{status} </if>
         ORDER BY id DESC
     </select>
+    <select id="selectFsSopDoctorTaskById" resultType="com.fs.his.domain.FsSopDoctorTask">
+        SELECT * FROM fs_sop_doctor_task WHERE id = #{id}
+    </select>
 </mapper>

+ 6 - 2
fs-service/src/main/resources/mapper/qw/FsDoctorMemberSalesMapper.xml

@@ -85,18 +85,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </delete>
 
     <select id="selectFsDoctorMemberSalesVOList" parameterType="com.fs.qw.param.FsDoctorMemberSalesQueryParam" resultType="com.fs.qw.vo.FsDoctorMemberSalesVO">
-        SELECT dms.*,qec.name userName,cu.nick_name companyUserName,u.phone,fuic.user_name as realName FROM fs_doctor_member_sales dms
+        SELECT dms.*,qec.name userName,cu.nick_name companyUserName,u.phone,fuic.user_name as realName,fd.doctor_name AS doctorName FROM fs_doctor_member_sales dms
         LEFT JOIN qw_external_contact qec ON dms.ex_id = qec.id
         LEFT JOIN company_user cu ON dms.company_user_id = cu.user_id
         LEFT JOIN fs_user u ON dms.fs_user_id = u.user_id
         LEFT JOIN fs_user_information_collection fuic ON dms.fs_user_id = fuic.user_id
-        WHERE dms.doctor_id = #{doctorId}
+        LEFT JOIN fs_doctor fd ON dms.doctor_id = fd.doctor_id
+        WHERE 1=1
         <if test="exId != null "> and dms.ex_id = #{exId}</if>
+        <if test="doctorId != null "> and dms.doctor_id = #{doctorId}</if>
+        <if test="companyUserId != null "> and dms.company_user_id = #{companyUserId}</if>
         <if test="startTime != null ">  and DATE(dms.create_time) &gt;= DATE(#{startTime})</if>
         <if test="endTime != null ">  and DATE(dms.create_time) &lt;= DATE(#{endTime})</if>
         <if test="userName != null and userName != '' "> and qec.name like concat('%', #{userName}, '%')</if>
         <if test="realName != null and realName != '' "> and fuic.user_name like concat('%', #{realName}, '%')</if>
         <if test="companyUserName != null and companyUserName != '' "> and cu.nick_name like concat('%', #{companyUserName}, '%')</if>
+        <if test="doctorName != null and doctorName != '' ">and fd.doctor_name like concat('%', #{doctorName}, '%')</if>
         order by dms.create_time desc
     </select>
     <select id="selectDoctorTaskStats" parameterType="com.fs.his.param.DoctorTaskStatsParam" resultType="com.fs.qw.vo.DoctorTaskStatsVO">