package com.ruoyi.basic.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.basic.dto.CustomerDto; import com.ruoyi.basic.dto.CustomerFollowUpDto; import com.ruoyi.basic.mapper.CustomerMapper; import com.ruoyi.basic.pojo.*; import com.ruoyi.basic.service.CustomerFollowUpFileService; import com.ruoyi.basic.service.CustomerFollowUpService; import com.ruoyi.basic.service.CustomerReturnVisitService; import com.ruoyi.basic.service.CustomerUserService; import com.ruoyi.basic.service.ICustomerService; import com.ruoyi.basic.vo.CustomerVo; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.framework.security.LoginUser; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.sales.mapper.SalesLedgerMapper; import com.ruoyi.sales.pojo.SalesLedger; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.web.multipart.MultipartFile; import java.time.ZoneId; import java.util.*; import java.util.stream.Collectors; /** * 客户档案Service业务层处理 * * @author ruoyi * @date 2025-05-07 */ @Service @AllArgsConstructor @Slf4j public class CustomerServiceImpl extends ServiceImpl implements ICustomerService { @Autowired private SalesLedgerMapper salesLedgerMapper; @Autowired private CustomerMapper customerMapper; @Autowired private CustomerFollowUpService customerFollowUpService; @Autowired private CustomerFollowUpFileService customerFollowUpFileService; @Autowired private CustomerReturnVisitService customerReturnVisitService; @Autowired private CustomerUserService customerUserService; /** * 查询客户档案 * * @param id 客户档案主键 * @return 客户档案 */ @Override public Customer selectCustomerById(Long id) { return customerMapper.selectById(id); } /** * 查询客户详情(含跟进记录和附件) * * @param id 客户档案主键 * @return 客户详情DTO */ @Override public CustomerVo selectCustomerDetailById(Long id) { CustomerVo customerVo = new CustomerVo(); BeanUtils.copyProperties(this.getById(id), customerVo); // 查询跟进记录 List followUpList = customerFollowUpService.list( new LambdaQueryWrapper() .eq(CustomerFollowUp::getCustomerId, id) .orderByDesc(CustomerFollowUp::getFollowUpTime) ); if (!com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(followUpList)) { List followUpDtoList = followUpList.stream().map(followUp -> { CustomerFollowUpDto followUpDto = new CustomerFollowUpDto(); BeanUtils.copyProperties(followUp, followUpDto); // 查询附件 List fileList = customerFollowUpFileService.list( new LambdaQueryWrapper() .eq(CustomerFollowUpFile::getFollowUpId, followUp.getId()) ); followUpDto.setFileList(fileList); return followUpDto; }).collect(Collectors.toList()); customerVo.setFollowUpList(followUpDtoList); } return customerVo; } /** * 查询客户档案列表 * * @param customer 客户档案 * @return 客户档案 */ @Override public IPage selectCustomerList(Page page, CustomerDto customer) { LoginUser loginUser = SecurityUtils.getLoginUser(); Long loginUserId = loginUser.getUserId(); IPage customerPage = customerMapper.listPage(page, customer, loginUserId); List records = customerPage.getRecords(); if (CollectionUtils.isEmpty(records)) { return customerPage; } List customerIds = records.stream() .map(CustomerVo::getId) .filter(Objects::nonNull) .collect(Collectors.toList()); if (!CollectionUtils.isEmpty(customerIds)) { Map latestFollowUpMap = getLatestFollowUpMap(customerIds); records.forEach(c -> { String address = StringUtils.defaultString(c.getCompanyAddress(), ""); String phone = StringUtils.defaultString(c.getCompanyPhone(), ""); c.setAddressPhone(address + "(" + phone + ")"); CustomerFollowUp followUp = latestFollowUpMap.get(c.getId()); if (followUp != null) { c.setFollowUpLevel(followUp.getFollowUpLevel()); c.setFollowUpTime(Date.from( followUp.getFollowUpTime().atZone(ZoneId.systemDefault()).toInstant() )); } // 转换共享用户ID字符串为List String userIdsStr = c.getUserIdsStr(); if (StringUtils.isNotEmpty(userIdsStr)) { List userIds = Arrays.stream(userIdsStr.split(",")) .map(String::trim) .map(Long::parseLong) .collect(Collectors.toList()); c.setUserIds(userIds); } }); } return customerPage; } private Map getLatestFollowUpMap(List customerIds) { List followUps = customerFollowUpService.list( new LambdaQueryWrapper() .in(CustomerFollowUp::getCustomerId, customerIds) .orderByDesc(CustomerFollowUp::getFollowUpTime) ); return followUps.stream() .collect(Collectors.toMap( CustomerFollowUp::getCustomerId, followUp -> followUp, (existing, replacement) -> existing )); } /** * 新增客户档案 * * @param customer 客户档案 * @return 结果 */ @Override public int insertCustomer(Customer customer) { LoginUser loginUser = SecurityUtils.getLoginUser(); Long tenantId = loginUser.getTenantId(); customer.setTenantId(tenantId); return customerMapper.insert(customer); } /** * 修改客户档案 * * @param customer 客户档案 * @return 结果 */ @Override public int updateCustomer(Customer customer) { LoginUser loginUser = SecurityUtils.getLoginUser(); Long tenantId = loginUser.getTenantId(); customer.setTenantId(tenantId); return customerMapper.updateById(customer); } /** * 批量删除客户档案 * * @param ids 需要删除的客户档案主键 * @return 结果 */ @Override @Transactional(rollbackFor = Exception.class) public int deleteCustomerByIds(Long[] ids) { List idList = Arrays.asList(ids); List salesLedgers = salesLedgerMapper.selectList(new QueryWrapper().lambda().in(SalesLedger::getCustomerId, idList)); if (!salesLedgers.isEmpty()) { throw new RuntimeException("客户档案下有销售合同,请先删除销售合同"); } // 查询是否有已分配的公海客户 List assignedPools = customerMapper.selectList( new QueryWrapper().lambda() .in(Customer::getId, idList) .eq(Customer::getType, 1). eq(Customer::getIsAssigned, 1) // 公海客户 ); if (!assignedPools.isEmpty()) { throw new RuntimeException("客户档案下有已分配的公海客户,请先收回"); } // 删除客户的同时也需要删除对应的客户跟随、附件和回访提醒 for (Long id : ids) { customerFollowUpService.deleteByCustomerId(id); customerReturnVisitService.deleteByCustomerId(id); // 删除客户的共享关系 customerUserService.remove( new QueryWrapper().lambda() .eq(CustomerUser::getCustomerId, id) ); } // 删除客户主表数据 return customerMapper.deleteBatchIds(idList); } @Override public List selectCustomerListByIds(Long[] ids) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.in(Customer::getId, Arrays.asList(ids)); return customerMapper.selectList(queryWrapper); } @Override public List selectCustomerLists(CustomerDto customer) { LoginUser loginUser = SecurityUtils.getLoginUser(); Long loginUserId = loginUser.getUserId(); return customerMapper.list(customer, loginUserId); } @Override public AjaxResult importData(MultipartFile file, Integer type) { try { ExcelUtil util = new ExcelUtil(Customer.class); List userList = util.importExcel(file.getInputStream()); if (CollectionUtils.isEmpty(userList)) { return AjaxResult.warn("模板错误或导入数据为空"); } // 根据 type 参数设置客户类型(私海/公海) if (type != null) { userList.forEach(customer -> { customer.setType(type); }); } this.saveOrUpdateBatch(userList); return AjaxResult.success(true); } catch (Exception e) { e.printStackTrace(); return AjaxResult.error("导入失败"); } } @Override public List> customerList(Customer customer) { LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(); queryWrapper.select(Customer::getId, Customer::getCustomerName, Customer::getTaxpayerIdentificationNumber); // 获取原始查询结果 List> result = customerMapper.selectMaps(queryWrapper); // 将下划线命名转换为驼峰命名 return result.stream().map(map -> map.entrySet().stream() .collect(Collectors.toMap( entry -> underlineToCamel(entry.getKey()), Map.Entry::getValue)) ).collect(Collectors.toList()); } // 分配公海客户给私海 @Override public void assignCustomer(CustomerDto customerDto) { Customer customer = customerMapper.selectById(customerDto.getId()); if (customer.getType() == 1 && customer.getIsAssigned() == 0) { // 公海且可分配 customer.setIsAssigned(1); customer.setUsageStatus(1L); customer.setUsageUser(customerDto.getUsageUser()); customerMapper.updateById(customer); } } // 回收私海客户到公海 @Override @Transactional(rollbackFor = Exception.class) public void recycleCustomer(CustomerDto customerDto) { Customer customer = customerMapper.selectById(customerDto.getId()); if (customer.getType() == 1 && customer.getIsAssigned() == 1) { // 公海且已分配 customer.setIsAssigned(0); customer.setUsageStatus(0L); customer.setUsageUser(0L); customerMapper.updateById(customer); // 删除该客户的所有共享关系 customerUserService.remove( new QueryWrapper().lambda() .eq(CustomerUser::getCustomerId, customerDto.getId()) ); } } // 客户共享 @Override public void together(CustomerDto customerDto) { // 查询现有的共享记录 List existingUsers = customerUserService.list( new QueryWrapper().lambda().eq(CustomerUser::getCustomerId, customerDto.getId()) ); // 获取已存在的用户ID列表 List existingUserIds = existingUsers.stream() .map(CustomerUser::getUserId) .collect(Collectors.toList()); // 过滤掉已存在的用户,只保留新用户 List newUserIds = customerDto.getUserIds().stream() .filter(userId -> !existingUserIds.contains(userId)) .collect(Collectors.toList()); if (CollectionUtils.isEmpty(newUserIds)) { return; } // 获取当前租户ID LoginUser loginUser = SecurityUtils.getLoginUser(); Long tenantId = loginUser.getTenantId(); // 批量保存新的共享记录 List customerUsers = newUserIds.stream() .map(userId -> { CustomerUser customerUser = new CustomerUser(); customerUser.setCustomerId(customerDto.getId()); customerUser.setUserId(userId); customerUser.setTenantId(tenantId); return customerUser; }) .collect(Collectors.toList()); customerUserService.saveBatch(customerUsers); } /** * 下划线命名转驼峰命名 */ private String underlineToCamel(String param) { if (param == null || "".equals(param.trim())) { return ""; } int len = param.length(); StringBuilder sb = new StringBuilder(len); for (int i = 0; i < len; i++) { char c = param.charAt(i); if (c == '_') { if (++i < len) { sb.append(Character.toUpperCase(param.charAt(i))); } } else { sb.append(Character.toLowerCase(c)); } } return sb.toString(); } }