Ver Fonte

红德堂-总后台项目会员转移导入

Long há 2 semanas atrás
pai
commit
357f2dcdea
20 ficheiros alterados com 852 adições e 15 exclusões
  1. 62 14
      fs-admin/src/main/java/com/fs/his/controller/FsUserController.java
  2. 5 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyMapper.java
  3. 5 0
      fs-service/src/main/java/com/fs/course/domain/FsUserCompanyUser.java
  4. 61 0
      fs-service/src/main/java/com/fs/his/domain/FsUserCompanyUserTransferTask.java
  5. 106 0
      fs-service/src/main/java/com/fs/his/domain/FsUserCompanyUserTransferTaskDetail.java
  6. 18 0
      fs-service/src/main/java/com/fs/his/dto/FsUserTransferImportDTO.java
  7. 22 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserCompanyUserTransferTaskDetailMapper.java
  8. 15 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserCompanyUserTransferTaskMapper.java
  9. 6 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserMapper.java
  10. 21 0
      fs-service/src/main/java/com/fs/his/service/IFsUserCompanyUserTransferTaskDetailService.java
  11. 33 0
      fs-service/src/main/java/com/fs/his/service/IFsUserCompanyUserTransferTaskService.java
  12. 33 0
      fs-service/src/main/java/com/fs/his/service/impl/FsUserCompanyUserTransferTaskDetailServiceImpl.java
  13. 251 0
      fs-service/src/main/java/com/fs/his/service/impl/FsUserCompanyUserTransferTaskServiceImpl.java
  14. 102 0
      fs-service/src/main/java/com/fs/his/vo/FsUserCompanyUserTransferTaskDetailVO.java
  15. 57 0
      fs-service/src/main/java/com/fs/his/vo/FsUserCompanyUserTransferTaskVO.java
  16. 9 0
      fs-service/src/main/resources/mapper/company/CompanyMapper.xml
  17. 6 1
      fs-service/src/main/resources/mapper/course/FsUserCompanyUserMapper.xml
  18. 10 0
      fs-service/src/main/resources/mapper/his/FsUserMapper.xml
  19. 20 0
      fs-service/src/main/resources/mapper/his/FsUserUserCompanyTransferTaskDetailMapper.xml
  20. 10 0
      fs-service/src/main/resources/mapper/his/FsUserUserCompanyTransferTaskMapper.xml

+ 62 - 14
fs-admin/src/main/java/com/fs/his/controller/FsUserController.java

@@ -1,47 +1,39 @@
 package com.fs.his.controller;
 
 import java.util.*;
-import java.util.stream.Collectors;
 
 import com.alibaba.fastjson.JSON;
-import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.core.domain.entity.SysRole;
 import com.fs.common.core.domain.entity.SysUser;
-import com.fs.common.exception.CustomException;
-import com.fs.common.utils.ParseUtils;
+import com.fs.common.exception.ServiceException;
 import com.fs.common.utils.SecurityUtils;
 import com.fs.common.utils.StringUtils;
-import com.fs.course.dto.BatchSendCourseDTO;
-import com.fs.course.param.FsCourseLinkCreateParam;
 import com.fs.course.service.IFsUserCompanyUserService;
-import com.fs.course.service.IFsUserCourseService;
 import com.fs.his.domain.FsUserAddress;
+import com.fs.his.domain.FsUserCompanyUserTransferTask;
 import com.fs.his.dto.FsUserDTO;
 import com.fs.his.enums.FsUserIntegralLogTypeEnum;
-import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.param.FsUserAddIntegralTemplateParam;
 import com.fs.his.param.FsUserAddPointsParam;
 import com.fs.his.param.FsUserParam;
+import com.fs.his.dto.FsUserTransferImportDTO;
+import com.fs.his.service.IFsUserCompanyUserTransferTaskService;
 import com.fs.his.service.IFsUserIntegralLogsService;
 import com.fs.his.utils.PhoneUtil;
-import com.fs.his.vo.FsUserExportListVO;
+import com.fs.his.vo.FsUserCompanyUserTransferTaskDetailVO;
+import com.fs.his.vo.FsUserCompanyUserTransferTaskVO;
 import com.fs.his.vo.FsUserVO;
 import com.fs.his.vo.UserVo;
-import com.fs.im.dto.OpenImResponseDTO;
-import com.fs.im.service.OpenIMService;
 import com.fs.qw.dto.UserProjectDTO;
 import com.fs.store.param.h5.FsUserPageListParam;
 import com.fs.store.vo.h5.FsUserPageListVO;
 import com.fs.system.service.ISysRoleService;
-import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import com.google.common.collect.Lists;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.ibatis.session.ExecutorType;
-import org.apache.ibatis.session.SqlSession;
 import org.apache.ibatis.session.SqlSessionFactory;
 import org.springframework.beans.BeanUtils;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -63,6 +55,7 @@ import com.fs.his.domain.FsUser;
 import com.fs.his.service.IFsUserService;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.common.core.page.TableDataInfo;
+import org.springframework.web.multipart.MultipartFile;
 
 import static com.fs.his.utils.PhoneUtil.*;
 
@@ -83,6 +76,8 @@ public class FsUserController extends BaseController
     private IFsUserIntegralLogsService userIntegralLogsService;
     @Autowired
     private IFsUserCompanyUserService userCompanyUserService;
+    @Autowired
+    private IFsUserCompanyUserTransferTaskService userTransferTaskService;
 
     @Autowired
     private SqlSessionFactory sqlSessionFactory;
@@ -403,5 +398,58 @@ public class FsUserController extends BaseController
         return userIntegralLogsService.addIntegralTemplate(integralTemplateParam);
     }
 
+    @ApiOperation("下载模板")
+    @GetMapping("/importTemplate")
+    public AjaxResult importTemplate() {
+        ExcelUtil<FsUserTransferImportDTO> util = new ExcelUtil<>(FsUserTransferImportDTO.class);
+        return util.importTemplateExcel("会员转移模板");
+    }
+
+    @ApiOperation("转移导入会员数据")
+    @Log(title = "转移导入会员数据", businessType = BusinessType.IMPORT)
+    @PreAuthorize("@ss.hasPermi('his:user:importData')")
+    @PostMapping("/importData")
+    public AjaxResult importData(MultipartFile file) {
+        ExcelUtil<FsUserTransferImportDTO> util = new ExcelUtil<>(FsUserTransferImportDTO.class);
+        List<FsUserTransferImportDTO> list;
+        try {
+            list = util.importExcel(file.getInputStream());
+        } catch (Exception e) {
+            throw new ServiceException("读取会员转移数据失败");
+        }
+
+        if (list.isEmpty()) {
+            throw new ServiceException("会员转移数据不能为空");
+        }
+
+        SysUser user = SecurityUtils.getLoginUser().getUser();
+        userTransferTaskService.transferImportData(list, user);
+
+        return AjaxResult.success();
+    }
+
+    @ApiOperation("转移导入会员数据列表")
+    @GetMapping("/transferTaskList")
+    public TableDataInfo transferTaskList() {
+        startPage();
+        List<FsUserCompanyUserTransferTaskVO> list = userTransferTaskService.getAllTransferTaskList();
+        return getDataTable(list);
+    }
+
+    @ApiOperation("转移导入会员数据详情")
+    @GetMapping("/transferTaskDetails/{taskId}")
+    public TableDataInfo transferTaskDetails(@PathVariable Long taskId) {
+        startPage();
+        List<FsUserCompanyUserTransferTaskDetailVO> list = userTransferTaskService.getAllTransferTaskDetails(taskId);
+        return getDataTable(list);
+    }
+
+    @ApiOperation("导出失败数据")
+    @GetMapping("/downloadFailedData/{taskId}")
+    public AjaxResult downloadFailedData(@PathVariable Long taskId) {
+        List<FsUserTransferImportDTO> list = userTransferTaskService.getTransferFailedData(taskId);
+        ExcelUtil<FsUserTransferImportDTO> util = new ExcelUtil<>(FsUserTransferImportDTO.class);
+        return util.exportExcel(list,"会员转移失败数据");
+    }
 
 }

+ 5 - 0
fs-service/src/main/java/com/fs/company/mapper/CompanyMapper.java

@@ -197,6 +197,11 @@ public interface CompanyMapper
 
     List<Company> selectCompanyByIds2(@Param("companyIds") Set<Long> companyIds);
 
+    /**
+     * 根据id查询公司列表
+     */
+    List<Company> selectCompanyByIds3(@Param("companyIds") Set<Long> companyIds);
+
 
     List<CompanyUser> selectCompanyListByIds(@Param("userIds") String result);
 

+ 5 - 0
fs-service/src/main/java/com/fs/course/domain/FsUserCompanyUser.java

@@ -71,5 +71,10 @@ public class FsUserCompanyUser {
      */
     private LocalDateTime createTime;
 
+    /**
+     * 修改时间
+     */
+    private LocalDateTime updateTime;
+
 
 }

+ 61 - 0
fs-service/src/main/java/com/fs/his/domain/FsUserCompanyUserTransferTask.java

@@ -0,0 +1,61 @@
+package com.fs.his.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+@TableName("fs_user_company_user_transfer_task")
+public class FsUserCompanyUserTransferTask {
+
+    /**
+     * 主键ID
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 状态 1执行成功 2执行失败
+     */
+    @TableField("`status`")
+    private Integer status;
+
+    /**
+     * 总条数
+     */
+    private Integer totalCount;
+
+    /**
+     * 成功条数
+     */
+    private Integer successCount;
+
+    /**
+     * 失败条数
+     */
+    private Integer failCount;
+
+    /**
+     * 提交人ID
+     */
+    private Long submitUserId;
+
+    /**
+     * 提交人昵称
+     */
+    private String submitUserName;
+
+    /**
+     * 上传时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 执行完成时间
+     */
+    private LocalDateTime finishTime;
+}

+ 106 - 0
fs-service/src/main/java/com/fs/his/domain/FsUserCompanyUserTransferTaskDetail.java

@@ -0,0 +1,106 @@
+package com.fs.his.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+@TableName("fs_user_company_user_transfer_task_detail")
+public class FsUserCompanyUserTransferTaskDetail {
+
+    /**
+     * 主键ID
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 任务ID
+     */
+    private Long taskId;
+
+    /**
+     * 原归属公司
+     */
+    private Long oldCompanyId;
+
+    /**
+     * 原归属公司名称
+     */
+    private String oldCompanyName;
+
+    /**
+     * 原归属销售
+     */
+    private Long oldCompanyUserId;
+
+    /**
+     * 原归属销售名称
+     */
+    private String oldCompanyUserName;
+
+    /**
+     * 项目
+     */
+    private Long projectId;
+
+    /**
+     * 项目名称
+     */
+    private String projectName;
+
+    /**
+     * 用户
+     */
+    private Long userId;
+
+    /**
+     * 用户名称
+     */
+    private String userName;
+
+    /**
+     * 新归属公司
+     */
+    private Long newCompanyId;
+
+    /**
+     * 新归属公司名称
+     */
+    private String newCompanyName;
+
+    /**
+     * 新归属销售
+     */
+    private Long newCompanyUserId;
+
+    /**
+     * 新归属销售名称
+     */
+    private String newCompanyUserName;
+
+    /**
+     * 上传时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 完成时间
+     */
+    private LocalDateTime finishTime;
+
+    /**
+     * 状态 1执行成功 2执行失败
+     */
+    @TableField("`status`")
+    private Integer status;
+
+    /**
+     * 失败原因
+     */
+    private String reason;
+}

+ 18 - 0
fs-service/src/main/java/com/fs/his/dto/FsUserTransferImportDTO.java

@@ -0,0 +1,18 @@
+package com.fs.his.dto;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class FsUserTransferImportDTO {
+
+    @Excel(name = "原归属销售ID")
+    private Long oldCompanyUserId;
+
+    @Excel(name = "客户ID")
+    private Long userId;
+
+    @Excel(name = "新归属销售ID")
+    private Long newCompanyUserId;
+
+}

+ 22 - 0
fs-service/src/main/java/com/fs/his/mapper/FsUserCompanyUserTransferTaskDetailMapper.java

@@ -0,0 +1,22 @@
+package com.fs.his.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.his.domain.FsUserCompanyUserTransferTaskDetail;
+import com.fs.his.dto.FsUserTransferImportDTO;
+import com.fs.his.vo.FsUserCompanyUserTransferTaskDetailVO;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface FsUserCompanyUserTransferTaskDetailMapper extends BaseMapper<FsUserCompanyUserTransferTaskDetail> {
+
+    /**
+     * 获取任务详情
+     */
+    List<FsUserCompanyUserTransferTaskDetailVO> getTaskDetailsByTaskId(@Param("taskId") Long taskId);
+
+    /**
+     * 获取转移失败数据
+     */
+    List<FsUserTransferImportDTO> getTransferFailedData(@Param("taskId") Long taskId);
+}

+ 15 - 0
fs-service/src/main/java/com/fs/his/mapper/FsUserCompanyUserTransferTaskMapper.java

@@ -0,0 +1,15 @@
+package com.fs.his.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.his.domain.FsUserCompanyUserTransferTask;
+import com.fs.his.vo.FsUserCompanyUserTransferTaskVO;
+
+import java.util.List;
+
+public interface FsUserCompanyUserTransferTaskMapper extends BaseMapper<FsUserCompanyUserTransferTask> {
+
+    /**
+     * 获取导入会员数据列表
+     */
+    List<FsUserCompanyUserTransferTaskVO> getAllTransferTaskList();
+}

+ 6 - 0
fs-service/src/main/java/com/fs/his/mapper/FsUserMapper.java

@@ -24,6 +24,7 @@ import com.fs.store.vo.UserProjectPair;
 import com.fs.store.vo.h5.*;
 import com.fs.watch.domain.vo.FsUserAndCompanyAndDoctorVo;
 import org.apache.ibatis.annotations.*;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * 用户Mapper接口
@@ -455,4 +456,9 @@ public interface FsUserMapper
     @Update("update fs_user set pay_count=pay_count+1" +
             " where user_id=#{userId}")
     void incPayCount(Long aLong);
+
+    /**
+     * 查询会员列表
+     */
+    List<FsUser> findUsersByIdsV2(@Param("userIds") List<Long> userIds);
 }

+ 21 - 0
fs-service/src/main/java/com/fs/his/service/IFsUserCompanyUserTransferTaskDetailService.java

@@ -0,0 +1,21 @@
+package com.fs.his.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.his.domain.FsUserCompanyUserTransferTaskDetail;
+import com.fs.his.dto.FsUserTransferImportDTO;
+import com.fs.his.vo.FsUserCompanyUserTransferTaskDetailVO;
+
+import java.util.List;
+
+public interface IFsUserCompanyUserTransferTaskDetailService extends IService<FsUserCompanyUserTransferTaskDetail> {
+
+    /**
+     * 获取任务详情
+     */
+    List<FsUserCompanyUserTransferTaskDetailVO> getTaskDetailsByTaskId(Long taskId);
+
+    /**
+     * 获取转移失败数据
+     */
+    List<FsUserTransferImportDTO> getTransferFailedData(Long taskId);
+}

+ 33 - 0
fs-service/src/main/java/com/fs/his/service/IFsUserCompanyUserTransferTaskService.java

@@ -0,0 +1,33 @@
+package com.fs.his.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.common.core.domain.entity.SysUser;
+import com.fs.his.domain.FsUserCompanyUserTransferTask;
+import com.fs.his.dto.FsUserTransferImportDTO;
+import com.fs.his.vo.FsUserCompanyUserTransferTaskDetailVO;
+import com.fs.his.vo.FsUserCompanyUserTransferTaskVO;
+
+import java.util.List;
+
+public interface IFsUserCompanyUserTransferTaskService extends IService<FsUserCompanyUserTransferTask> {
+
+    /**
+     * 转移导入会员数据
+     */
+    void transferImportData(List<FsUserTransferImportDTO> list, SysUser user);
+
+    /**
+     * 获取导入会员数据列表
+     */
+    List<FsUserCompanyUserTransferTaskVO> getAllTransferTaskList();
+
+    /**
+     * 获取导入会员数据详情
+     */
+    List<FsUserCompanyUserTransferTaskDetailVO> getAllTransferTaskDetails(Long taskId);
+
+    /**
+     * 获取转移失败数据
+     */
+    List<FsUserTransferImportDTO> getTransferFailedData(Long taskId);
+}

+ 33 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsUserCompanyUserTransferTaskDetailServiceImpl.java

@@ -0,0 +1,33 @@
+package com.fs.his.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.his.domain.FsUserCompanyUserTransferTaskDetail;
+import com.fs.his.dto.FsUserTransferImportDTO;
+import com.fs.his.mapper.FsUserCompanyUserTransferTaskDetailMapper;
+import com.fs.his.service.IFsUserCompanyUserTransferTaskDetailService;
+import com.fs.his.vo.FsUserCompanyUserTransferTaskDetailVO;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.List;
+
+@Service
+public class FsUserCompanyUserTransferTaskDetailServiceImpl extends ServiceImpl<FsUserCompanyUserTransferTaskDetailMapper, FsUserCompanyUserTransferTaskDetail>
+        implements IFsUserCompanyUserTransferTaskDetailService {
+
+    /**
+     * 获取任务详情
+     */
+    @Override
+    public List<FsUserCompanyUserTransferTaskDetailVO> getTaskDetailsByTaskId(Long taskId) {
+        return baseMapper.getTaskDetailsByTaskId(taskId);
+    }
+
+    /**
+     * 获取转移失败数据
+     */
+    @Override
+    public List<FsUserTransferImportDTO> getTransferFailedData(Long taskId) {
+        return baseMapper.getTransferFailedData(taskId);
+    }
+}

+ 251 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsUserCompanyUserTransferTaskServiceImpl.java

@@ -0,0 +1,251 @@
+package com.fs.his.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.core.domain.entity.SysUser;
+import com.fs.common.exception.ServiceException;
+import com.fs.common.utils.StringUtils;
+import com.fs.common.utils.bean.BeanUtils;
+import com.fs.company.domain.Company;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.mapper.CompanyMapper;
+import com.fs.company.mapper.CompanyUserMapper;
+import com.fs.course.domain.FsUserCompanyUser;
+import com.fs.course.service.IFsUserCompanyUserService;
+import com.fs.his.domain.FsUser;
+import com.fs.his.domain.FsUserCompanyUserTransferTask;
+import com.fs.his.domain.FsUserCompanyUserTransferTaskDetail;
+import com.fs.his.dto.FsUserTransferImportDTO;
+import com.fs.his.mapper.FsUserCompanyUserTransferTaskMapper;
+import com.fs.his.mapper.FsUserMapper;
+import com.fs.his.service.IFsUserCompanyUserTransferTaskDetailService;
+import com.fs.his.service.IFsUserCompanyUserTransferTaskService;
+import com.fs.his.vo.FsUserCompanyUserTransferTaskDetailVO;
+import com.fs.his.vo.FsUserCompanyUserTransferTaskVO;
+import com.fs.system.mapper.SysDictDataMapper;
+import com.fs.system.vo.DictVO;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@Service
+@AllArgsConstructor
+public class FsUserCompanyUserTransferTaskServiceImpl extends ServiceImpl<FsUserCompanyUserTransferTaskMapper, FsUserCompanyUserTransferTask>
+        implements IFsUserCompanyUserTransferTaskService {
+
+    private final IFsUserCompanyUserTransferTaskDetailService transferTaskDetailService;
+    private final FsUserMapper userMapper;
+    private final CompanyMapper companyMapper;
+    private final CompanyUserMapper companyUserMapper;
+    private final IFsUserCompanyUserService userCompanyUserService;
+    private final SysDictDataMapper sysDictDataMapper;
+
+    /**
+     * 转移导入会员数据
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void transferImportData(List<FsUserTransferImportDTO> list, SysUser user) {
+        FsUserCompanyUserTransferTask transferTask = new FsUserCompanyUserTransferTask();
+        transferTask.setStatus(0);
+        transferTask.setCreateTime(LocalDateTime.now());
+        transferTask.setTotalCount(list.size());
+        transferTask.setSubmitUserId(user.getUserId());
+        transferTask.setSubmitUserName(user.getUserName());
+        baseMapper.insert(transferTask);
+
+        // 查询所有的销售
+        Set<Long> companyUserIds = list.stream()
+                .flatMap(d -> Stream.of(d.getOldCompanyUserId(), d.getNewCompanyUserId()))
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+        List<CompanyUser> companyUsers = companyUserMapper.selectCompanyUserByIds(companyUserIds);
+        if (companyUsers.isEmpty()) {
+            throw new ServiceException("销售列表不能为空");
+        }
+
+        Map<Long, CompanyUser> companyUserMap = companyUsers.stream()
+                .filter(Objects::nonNull)
+                .filter(cu -> cu.getUserId() != null)
+                .collect(Collectors.toMap(CompanyUser::getUserId, Function.identity(), (a, b) -> a));
+
+        // 查询所有的公司
+        Set<Long> companyIds = companyUsers.stream()
+                .map(CompanyUser::getCompanyId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+        List<Company> companies = companyMapper.selectCompanyByIds3(companyIds);
+        if (companies.isEmpty()) {
+            throw new ServiceException("销售对应公司不存在");
+        }
+
+        Map<Long, Company> companyMap = companies.stream()
+                .filter(Objects::nonNull)
+                .filter(c -> c.getCompanyId() != null)
+                .collect(Collectors.toMap(Company::getCompanyId, Function.identity(), (a, b) -> a));
+
+
+        // 查询所有的用户
+        List<Long> userIds = list.stream().map(FsUserTransferImportDTO::getUserId).collect(Collectors.toList());
+        List<FsUser> users = userMapper.findUsersByIdsV2(userIds);
+        if (users.isEmpty()) {
+            throw new ServiceException("转移会员不能为空");
+        }
+
+       Map<Long, FsUser> userMap = users.stream()
+                .filter(Objects::nonNull)
+                .filter(u -> u.getUserId() != null)
+                .collect(Collectors.toMap(FsUser::getUserId, Function.identity(), (a, b) -> a));
+
+        // 获取所有项目
+        List<DictVO> dictVOS = sysDictDataMapper.selectDictDataListByType("sys_course_project");
+        Map<Long, String> dictMap = dictVOS.stream()
+                .filter(Objects::nonNull)
+                .filter(d -> StringUtils.isNotBlank(d.getDictValue()))
+                .collect(Collectors.toMap(d -> Long.valueOf(d.getDictValue()), DictVO::getDictLabel, (a, b) -> a));
+
+        List<FsUserCompanyUser> updateRelations = new ArrayList<>();
+        List<FsUserCompanyUserTransferTaskDetail> details = new ArrayList<>();
+        for (FsUserTransferImportDTO fsUserTransferImportDTO : list) {
+            FsUserCompanyUserTransferTaskDetail detail = new FsUserCompanyUserTransferTaskDetail();
+            detail.setTaskId(transferTask.getId());
+            detail.setCreateTime(LocalDateTime.now());
+
+            try {
+                boolean flag = true;
+                StringBuilder reason = new StringBuilder();
+
+                Long oldCompanyUserId = fsUserTransferImportDTO.getOldCompanyUserId();
+                CompanyUser oldCompanyUser = oldCompanyUserId == null ? null : companyUserMap.get(oldCompanyUserId);
+                if (oldCompanyUser != null) {
+                    Company company = companyMap.get(oldCompanyUser.getCompanyId());
+                    if (company != null) {
+                        detail.setOldCompanyId(company.getCompanyId());
+                        detail.setOldCompanyName(company.getCompanyName());
+                    } else {
+                        flag = false;
+                        reason.append("原销售公司不存在[").append(oldCompanyUser.getCompanyId()).append("],");
+                    }
+
+                    detail.setOldCompanyUserId(oldCompanyUser.getUserId());
+                    detail.setOldCompanyUserName(oldCompanyUser.getUserName());
+                } else {
+                    flag = false;
+                    reason.append("原销售不存在[").append(oldCompanyUserId).append("],");
+                }
+
+                Long userId = fsUserTransferImportDTO.getUserId();
+                FsUser fsUser = userId == null ? null : userMap.get(userId);
+                if (fsUser != null) {
+                    detail.setUserId(fsUser.getUserId());
+                    detail.setUserName(fsUser.getNickName());
+                } else {
+                    flag = false;
+                    reason.append("会员不存在[").append(userId).append("],");
+                }
+
+                Long newCompanyUserId = fsUserTransferImportDTO.getNewCompanyUserId();
+                CompanyUser newCompanyUser = newCompanyUserId == null ? null : companyUserMap.get(newCompanyUserId);
+                if (newCompanyUser != null) {
+                    Company company = companyMap.get(newCompanyUser.getCompanyId());
+                    if (company != null) {
+                        detail.setNewCompanyId(company.getCompanyId());
+                        detail.setNewCompanyName(company.getCompanyName());
+                    } else {
+                        flag = false;
+                        reason.append("新归属销售公司不存在[").append(newCompanyUser.getCompanyId()).append("],");
+                    }
+
+                    detail.setNewCompanyUserId(newCompanyUser.getUserId());
+                    detail.setNewCompanyUserName(newCompanyUser.getUserName());
+                } else {
+                    flag = false;
+                    reason.append("新归属销售不存在[").append(newCompanyUserId).append("],");
+                }
+
+                if (flag) {
+                    FsUserCompanyUser params = new FsUserCompanyUser();
+                    params.setCompanyId(detail.getOldCompanyId());
+                    params.setCompanyUserId(detail.getOldCompanyUserId());
+                    params.setUserId(detail.getUserId());
+                    List<FsUserCompanyUser> fsUserCompanyUsers = userCompanyUserService.selectFsUserCompanyUserList(params);
+                    if (!fsUserCompanyUsers.isEmpty()) {
+                        for (FsUserCompanyUser u : fsUserCompanyUsers) {
+                            u.setCompanyId(detail.getNewCompanyId());
+                            u.setCompanyUserId(detail.getNewCompanyUserId());
+                            u.setUpdateTime(LocalDateTime.now());
+                            updateRelations.add(u);
+
+                            FsUserCompanyUserTransferTaskDetail copyDetail = new FsUserCompanyUserTransferTaskDetail();
+                            BeanUtils.copyProperties(detail, copyDetail);
+                            copyDetail.setFinishTime(LocalDateTime.now());
+                            copyDetail.setStatus(1);
+                            copyDetail.setProjectId(u.getProjectId());
+                            copyDetail.setProjectName(dictMap.get(u.getProjectId()));
+                            details.add(copyDetail);
+                        }
+                    } else {
+                        reason.append("会员[").append(detail.getUserId()).append("]与销售[").append(detail.getOldCompanyUserId()).append("]归属关系不正确,");
+                        detail.setStatus(2);
+                        detail.setReason(StringUtils.removeEnd(reason.toString(), ","));
+                        detail.setFinishTime(LocalDateTime.now());
+                        details.add(detail);
+                    }
+                } else {
+                    detail.setStatus(2);
+                    detail.setReason(StringUtils.removeEnd(reason.toString(), ","));
+                    detail.setFinishTime(LocalDateTime.now());
+                    details.add(detail);
+                }
+            } catch (Exception e) {
+                detail.setStatus(2);
+                detail.setReason(e.getMessage());
+                detail.setFinishTime(LocalDateTime.now());
+                details.add(detail);
+            }
+        }
+
+        if (!details.isEmpty()) {
+            transferTaskDetailService.saveBatch(details);
+        }
+
+        if (!updateRelations.isEmpty()) {
+            userCompanyUserService.updateBatchById(updateRelations);
+        }
+
+        transferTask.setSuccessCount((int) details.stream().filter(d -> d.getStatus() == 1).count());
+        transferTask.setFailCount((int) details.stream().filter(d -> d.getStatus() == 2).count());
+        transferTask.setStatus(1);
+        transferTask.setFinishTime(LocalDateTime.now());
+        baseMapper.updateById(transferTask);
+    }
+
+    /**
+     * 获取导入会员数据列表
+     */
+    @Override
+    public List<FsUserCompanyUserTransferTaskVO> getAllTransferTaskList() {
+        return baseMapper.getAllTransferTaskList();
+    }
+
+    /**
+     * 获取导入会员数据详情
+     */
+    @Override
+    public List<FsUserCompanyUserTransferTaskDetailVO> getAllTransferTaskDetails(Long taskId) {
+        return transferTaskDetailService.getTaskDetailsByTaskId(taskId);
+    }
+
+    /**
+     * 获取转移失败数据
+     */
+    @Override
+    public List<FsUserTransferImportDTO> getTransferFailedData(Long taskId) {
+        return transferTaskDetailService.getTransferFailedData(taskId);
+    }
+}

+ 102 - 0
fs-service/src/main/java/com/fs/his/vo/FsUserCompanyUserTransferTaskDetailVO.java

@@ -0,0 +1,102 @@
+package com.fs.his.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+public class FsUserCompanyUserTransferTaskDetailVO {
+
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 任务ID
+     */
+    private Long taskId;
+
+    /**
+     * 原归属公司
+     */
+    private Long oldCompanyId;
+
+    /**
+     * 原归属公司名称
+     */
+    private String oldCompanyName;
+
+    /**
+     * 原归属销售
+     */
+    private Long oldCompanyUserId;
+
+    /**
+     * 原归属销售名称
+     */
+    private String oldCompanyUserName;
+
+    /**
+     * 项目
+     */
+    private Long projectId;
+
+    /**
+     * 项目名称
+     */
+    private String projectName;
+
+    /**
+     * 用户
+     */
+    private Long userId;
+
+    /**
+     * 用户名称
+     */
+    private String userName;
+
+    /**
+     * 新归属公司
+     */
+    private Long newCompanyId;
+
+    /**
+     * 新归属公司名称
+     */
+    private String newCompanyName;
+
+    /**
+     * 新归属销售
+     */
+    private Long newCompanyUserId;
+
+    /**
+     * 新归属销售名称
+     */
+    private String newCompanyUserName;
+
+    /**
+     * 上传时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime createTime;
+
+    /**
+     * 完成时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime finishTime;
+
+    /**
+     * 状态 1执行成功 2执行失败
+     */
+    private Integer status;
+
+    /**
+     * 失败原因
+     */
+    private String reason;
+}

+ 57 - 0
fs-service/src/main/java/com/fs/his/vo/FsUserCompanyUserTransferTaskVO.java

@@ -0,0 +1,57 @@
+package com.fs.his.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+public class FsUserCompanyUserTransferTaskVO {
+
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 状态 1执行成功 2执行失败
+     */
+    private Integer status;
+
+    /**
+     * 总条数
+     */
+    private Integer totalCount;
+
+    /**
+     * 成功条数
+     */
+    private Integer successCount;
+
+    /**
+     * 失败条数
+     */
+    private Integer failCount;
+
+    /**
+     * 提交人ID
+     */
+    private Long submitUserId;
+
+    /**
+     * 提交人昵称
+     */
+    private String submitUserName;
+
+    /**
+     * 上传时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime createTime;
+
+    /**
+     * 执行完成时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime finishTime;
+}

+ 9 - 0
fs-service/src/main/resources/mapper/company/CompanyMapper.xml

@@ -242,6 +242,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{companyId}
         </foreach>
     </select>
+
+    <select id="selectCompanyByIds3" resultType="com.fs.company.domain.Company">
+        select * from company
+        where company_id in
+        <foreach item="companyId" collection="companyIds" open="(" separator="," close=")">
+            #{companyId}
+        </foreach>
+    </select>
+
     <select id="selectCompanyListByIds" resultType="com.fs.company.domain.CompanyUser">
         select role_id roleId,role_name roleName from fastgpt_role
         <where>

+ 6 - 1
fs-service/src/main/resources/mapper/course/FsUserCompanyUserMapper.xml

@@ -17,10 +17,11 @@
         <result property="status"    column="status"    />
         <result property="remark"    column="remark"    />
         <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
     </resultMap>
 
     <sql id="selectFsUserCompanyUserVo">
-        select id, user_id, company_user_id, company_id, is_repeat_fans, project_id, qw_user_id, qw_external_contact_id, qw_company_id, `status`, remark, create_time from fs_user_company_user
+        select id, user_id, company_user_id, company_id, is_repeat_fans, project_id, qw_user_id, qw_external_contact_id, qw_company_id, `status`, remark, create_time, update_time from fs_user_company_user
     </sql>
 
     <select id="selectFsUserCompanyUserList" parameterType="FsUserCompanyUser" resultMap="FsUserCompanyUserResult">
@@ -37,6 +38,7 @@
             <if test="status != null "> and `status` = #{status}</if>
             <if test="remark != null "> and remark = #{remark}</if>
             <if test="createTime != null "> and create_time = #{createTime}</if>
+            <if test="updateTime != null "> and update_time = #{updateTime}</if>
         </where>
     </select>
 
@@ -60,6 +62,7 @@
             <if test="status != null">`status`,</if>
             <if test="remark != null">remark,</if>
             <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="id != null">#{id},</if>
@@ -74,6 +77,7 @@
             <if test="status != null">#{status},</if>
             <if test="remark != null">#{remark},</if>
             <if test="createTime != null">#{createTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
         </trim>
     </insert>
 
@@ -91,6 +95,7 @@
             <if test="status != null">`status` = #{status},</if>
             <if test="remark != null">remark = #{remark},</if>
             <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
         </trim>
         where id = #{id}
     </update>

+ 10 - 0
fs-service/src/main/resources/mapper/his/FsUserMapper.xml

@@ -2320,5 +2320,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         GROUP BY user_id, project_id
     </select>
 
+    <select id="findUsersByIdsV2" resultMap="FsUserResult">
+        select
+            *
+        from fs_user
+        where user_id in
+        <foreach collection="userIds" item="userId" open="(" separator="," close=")">
+            #{userId}
+        </foreach>
+    </select>
+
 
 </mapper>

+ 20 - 0
fs-service/src/main/resources/mapper/his/FsUserUserCompanyTransferTaskDetailMapper.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.his.mapper.FsUserCompanyUserTransferTaskDetailMapper">
+
+    <select id="getTaskDetailsByTaskId" resultType="com.fs.his.vo.FsUserCompanyUserTransferTaskDetailVO">
+        select * from fs_user_company_user_transfer_task_detail where task_id = #{taskId}
+    </select>
+
+    <select id="getTransferFailedData" resultType="com.fs.his.dto.FsUserTransferImportDTO">
+        select
+            old_company_user_id as oldCompanyUserId,
+            user_id             as userId,
+            new_company_user_id as newCompanyUserId
+        from fs_user_company_user_transfer_task_detail
+        where task_id = #{taskId} and status = 2
+        group by old_company_user_id, user_id, new_company_user_id
+    </select>
+</mapper>

+ 10 - 0
fs-service/src/main/resources/mapper/his/FsUserUserCompanyTransferTaskMapper.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.his.mapper.FsUserCompanyUserTransferTaskMapper">
+
+    <select id="getAllTransferTaskList" resultType="com.fs.his.vo.FsUserCompanyUserTransferTaskVO">
+        select * from fs_user_company_user_transfer_task order by create_time desc
+    </select>
+</mapper>