|
|
@@ -1,26 +1,28 @@
|
|
|
package org.dromara.customer.service.impl;
|
|
|
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
-import org.dromara.common.core.utils.MapstructUtils;
|
|
|
-import org.dromara.common.core.utils.StringUtils;
|
|
|
-import org.dromara.common.mybatis.core.page.TableDataInfo;
|
|
|
-import org.dromara.common.mybatis.core.page.PageQuery;
|
|
|
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.dromara.common.core.context.PlatformContext;
|
|
|
+import org.dromara.common.core.utils.MapstructUtils;
|
|
|
+import org.dromara.common.core.utils.StringUtils;
|
|
|
+import org.dromara.common.mybatis.core.page.PageQuery;
|
|
|
+import org.dromara.common.mybatis.core.page.TableDataInfo;
|
|
|
import org.dromara.customer.domain.*;
|
|
|
import org.dromara.customer.domain.bo.*;
|
|
|
import org.dromara.customer.domain.vo.*;
|
|
|
import org.dromara.customer.mapper.*;
|
|
|
-import org.springframework.stereotype.Service;
|
|
|
import org.dromara.customer.service.ICustomerInfoService;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
import java.util.*;
|
|
|
-import java.util.function.Function;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
@@ -32,7 +34,7 @@ import java.util.stream.Collectors;
|
|
|
@Slf4j
|
|
|
@RequiredArgsConstructor
|
|
|
@Service
|
|
|
-public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, CustomerInfo> implements ICustomerInfoService {
|
|
|
+public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, CustomerInfo> implements ICustomerInfoService {
|
|
|
|
|
|
private final CustomerInfoMapper baseMapper;
|
|
|
private final CustomerBusinessInfoMapper customerBusinessInfoMapper;
|
|
|
@@ -41,6 +43,8 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cu
|
|
|
private final CustomerSalesInfoMapper customerSalesInfoMapper;
|
|
|
private final IndustryCategoryMapper industryCategoryMapper;
|
|
|
private final EnterpriseScaleMapper enterpriseScaleMapper;
|
|
|
+ private final CustomerInfoTagMapper customerInfoTagMapper;
|
|
|
+ private final CustomerContractMapper customerContractMapper;
|
|
|
|
|
|
|
|
|
/**
|
|
|
@@ -50,7 +54,7 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cu
|
|
|
* @return 客户信息
|
|
|
*/
|
|
|
@Override
|
|
|
- public CustomerInfoVo queryById(Long id){
|
|
|
+ public CustomerInfoVo queryById(Long id) {
|
|
|
if (id == null || id <= 0) {
|
|
|
return null;
|
|
|
}
|
|
|
@@ -61,12 +65,12 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cu
|
|
|
return null;
|
|
|
}
|
|
|
EnterpriseScaleVo enterpriseScaleVo = enterpriseScaleMapper.selectVoById(vo.getEnterpriseScaleId());
|
|
|
- if (enterpriseScaleVo != null){
|
|
|
+ if (enterpriseScaleVo != null) {
|
|
|
vo.setEnterpriseScale(enterpriseScaleVo.getEnterpriseScaleName());
|
|
|
}
|
|
|
|
|
|
IndustryCategoryVo industryCategoryVo = industryCategoryMapper.selectVoById(vo.getIndustryCategoryId());
|
|
|
- if (industryCategoryVo != null){
|
|
|
+ if (industryCategoryVo != null) {
|
|
|
vo.setIndustryCategory(industryCategoryVo.getIndustryCategoryName());
|
|
|
}
|
|
|
// 2. 查询关联信息
|
|
|
@@ -115,8 +119,8 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cu
|
|
|
LambdaQueryWrapper<CustomerInfo> lqw = buildQueryWrapper(bo);
|
|
|
Page<CustomerInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
|
|
List<CustomerInfoVo> records = result.getRecords();
|
|
|
- if (CollUtil.isNotEmpty( records)){
|
|
|
- Set<Long>industryIds = records.stream()
|
|
|
+ if (CollUtil.isNotEmpty(records)) {
|
|
|
+ Set<Long> industryIds = records.stream()
|
|
|
.map(CustomerInfoVo::getIndustryCategoryId)
|
|
|
.filter(Objects::nonNull)
|
|
|
.collect(Collectors.toSet());
|
|
|
@@ -137,6 +141,124 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cu
|
|
|
return TableDataInfo.build(result);
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public TableDataInfo<ContractVo> queryContractPageList(CustomerInfoBo bo, PageQuery pageQuery) {
|
|
|
+ LambdaQueryWrapper<CustomerInfo> lqw = buildQueryWrapper(bo);
|
|
|
+
|
|
|
+ Page<CustomerInfo> customerPage = baseMapper.selectPage(pageQuery.build(), lqw);
|
|
|
+ List<CustomerInfo> customerList = customerPage.getRecords();
|
|
|
+
|
|
|
+ if (CollUtil.isEmpty(customerList)) {
|
|
|
+ return new TableDataInfo<>(new ArrayList<>(), 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Long> customerIdList = customerList.stream()
|
|
|
+ .map(CustomerInfo::getId)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ List<Long> industryIdList = customerList.stream()
|
|
|
+ .map(CustomerInfo::getIndustryCategoryId)
|
|
|
+ .filter(Objects::nonNull) // 防止空指针
|
|
|
+ .distinct() // 去重,减少调用数据量
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ final Map<Long, String> industryCategoryMap = new HashMap<>();
|
|
|
+
|
|
|
+ if (!industryIdList.isEmpty()) {
|
|
|
+ List<IndustryCategoryVo> industryList = industryCategoryMapper.selectVoByIds(industryIdList);
|
|
|
+ industryCategoryMap.putAll(industryList.stream()
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ IndustryCategoryVo::getId,
|
|
|
+ vo -> Optional.ofNullable(vo.getIndustryCategoryName()).orElse(""),
|
|
|
+ (v1, v2) -> v1
|
|
|
+ ))
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取合同统计
|
|
|
+ Map<Long, ContractVo> contractStatMap = getContractStatsByCustomerIds(customerIdList);
|
|
|
+
|
|
|
+ // 获取部门名称映射
|
|
|
+ // Map<Long, String> deptNameMap = getDeptNameMapByCustomerIds(customerIdList);
|
|
|
+
|
|
|
+
|
|
|
+ // 构造最终返回数据
|
|
|
+ // 构造 VO
|
|
|
+ List<ContractVo> voList = customerList.stream().map(customer -> {
|
|
|
+ ContractVo vo = new ContractVo();
|
|
|
+ vo.setCustomerId(customer.getId());
|
|
|
+ vo.setCustomerNo(customer.getCustomerNo());
|
|
|
+
|
|
|
+ // ⚠️ 确认这里字段是否存在!
|
|
|
+ vo.setCustomerName(customer.getBusinessCustomerName()); // 或 customer.getShortName()
|
|
|
+
|
|
|
+ vo.setIndustryCategoryId(customer.getIndustryCategoryId());
|
|
|
+ vo.setIndustryCategory(industryCategoryMap.getOrDefault(customer.getIndustryCategoryId(), ""));
|
|
|
+
|
|
|
+ ContractVo stat = contractStatMap.getOrDefault(customer.getId(), new ContractVo());
|
|
|
+ vo.setContractCount(Optional.ofNullable(stat.getContractCount()).orElse(0));
|
|
|
+ vo.setEffectiveContract(Optional.ofNullable(stat.getEffectiveContract()).orElse(0));
|
|
|
+ vo.setInvalidContract(Optional.ofNullable(stat.getInvalidContract()).orElse(0));
|
|
|
+ vo.setVoidedContract(Optional.ofNullable(stat.getVoidedContract()).orElse(0));
|
|
|
+
|
|
|
+ return vo;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+
|
|
|
+ return new TableDataInfo<>(voList, customerPage.getTotal());
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<Long, ContractVo> getContractStatsByCustomerIds(List<Long> customerIdList) {
|
|
|
+ if (CollUtil.isEmpty(customerIdList)) {
|
|
|
+ return new HashMap<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 调用自定义 SQL
|
|
|
+ List<Map<String, Object>> stats = customerContractMapper.selectContractStatsByCustomerIds(customerIdList);
|
|
|
+
|
|
|
+ Map<Long, ContractVo> result = new HashMap<>();
|
|
|
+
|
|
|
+ for (Map<String, Object> row : stats) {
|
|
|
+ Long customerId = (Long) row.get("customer_id");
|
|
|
+ ContractVo vo = new ContractVo();
|
|
|
+
|
|
|
+ // 安全获取数值:防止 null
|
|
|
+ vo.setContractCount(getIntValue(row.get("total")));
|
|
|
+ vo.setEffectiveContract(getIntValue(row.get("effective")));
|
|
|
+ vo.setInvalidContract(getIntValue(row.get("invalid")));
|
|
|
+ vo.setVoidedContract(getIntValue(row.get("voided")));
|
|
|
+
|
|
|
+ result.put(customerId, vo);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 补全缺失的客户(无合同的客户)
|
|
|
+ for (Long id : customerIdList) {
|
|
|
+ result.putIfAbsent(id, createEmptyContractVo());
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 工具方法:安全转换 Object -> Integer
|
|
|
+ private int getIntValue(Object value) {
|
|
|
+ if (value == null) return 0;
|
|
|
+ if (value instanceof BigDecimal) {
|
|
|
+ return ((BigDecimal) value).intValue();
|
|
|
+ }
|
|
|
+ if (value instanceof Number) {
|
|
|
+ return ((Number) value).intValue();
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ private ContractVo createEmptyContractVo() {
|
|
|
+ ContractVo vo = new ContractVo();
|
|
|
+ vo.setContractCount(0);
|
|
|
+ vo.setEffectiveContract(0);
|
|
|
+ vo.setInvalidContract(0);
|
|
|
+ vo.setVoidedContract(0);
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 查询符合条件的客户信息列表
|
|
|
*
|
|
|
@@ -156,6 +278,7 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cu
|
|
|
lqw.eq(StringUtils.isNotBlank(bo.getCustomerNo()), CustomerInfo::getCustomerNo, bo.getCustomerNo());
|
|
|
lqw.eq(bo.getBelongCompanyId() != null, CustomerInfo::getBelongCompanyId, bo.getBelongCompanyId());
|
|
|
lqw.like(StringUtils.isNotBlank(bo.getCompanyName()), CustomerInfo::getCompanyName, bo.getCompanyName());
|
|
|
+ lqw.like(StringUtils.isNotBlank(bo.getCustomerName()), CustomerInfo::getCustomerName, bo.getCustomerName());
|
|
|
lqw.like(StringUtils.isNotBlank(bo.getBusinessCustomerName()), CustomerInfo::getBusinessCustomerName, bo.getBusinessCustomerName());
|
|
|
lqw.like(StringUtils.isNotBlank(bo.getShortName()), CustomerInfo::getShortName, bo.getShortName());
|
|
|
lqw.eq(bo.getInvoiceTypeId() != null, CustomerInfo::getInvoiceTypeId, bo.getInvoiceTypeId());
|
|
|
@@ -227,8 +350,6 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cu
|
|
|
customerBusinessInfoMapper.deleteByCustomerId(customerId);
|
|
|
// 删除销售信息(一对一)
|
|
|
customerSalesInfoMapper.deleteByCustomerId(customerId);
|
|
|
- // 删除联系人(一对多)
|
|
|
- customerContactMapper.deleteByCustomerId(customerId);
|
|
|
// 删除发票信息(一对多)
|
|
|
customerInvoiceInfoMapper.deleteByCustomerId(customerId);
|
|
|
}
|
|
|
@@ -295,7 +416,7 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cu
|
|
|
// 2. 删除旧的关联数据
|
|
|
customerBusinessInfoMapper.deleteByCustomerId(customerId);
|
|
|
customerSalesInfoMapper.deleteByCustomerId(customerId);
|
|
|
- customerContactMapper.deleteByCustomerId(customerId);
|
|
|
+// customerContactMapper.deleteByCustomerId(customerId);
|
|
|
customerInvoiceInfoMapper.deleteByCustomerId(customerId);
|
|
|
|
|
|
// 3. 插入新的关联数据
|
|
|
@@ -305,7 +426,7 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cu
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 保存客户的关联信息(不包含删除逻辑,仅插入)
|
|
|
+ * 保存客户的关联信息
|
|
|
*/
|
|
|
private void saveAssociatedData(Long customerId, CustomerInfoBo bo) {
|
|
|
// 业务信息
|
|
|
@@ -341,10 +462,89 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cu
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public int updateCustomerCheckStatus(Long customerId, String status) {
|
|
|
+ return baseMapper.update(null,
|
|
|
+ new LambdaUpdateWrapper<CustomerInfo>()
|
|
|
+ .set(CustomerInfo::getStatus, status)
|
|
|
+ .eq(CustomerInfo::getId, customerId));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int updateCreditAmount(List<Long> customerIds, BigDecimal creditAmount) {
|
|
|
+ if (customerIds == null || customerIds.isEmpty()) {
|
|
|
+ return 0; // 避免无效更新
|
|
|
+ }
|
|
|
+ return customerSalesInfoMapper.update(
|
|
|
+ null,
|
|
|
+ new LambdaUpdateWrapper<CustomerSalesInfo>()
|
|
|
+ .set(CustomerSalesInfo::getCreditAmount, creditAmount)
|
|
|
+ .in(CustomerSalesInfo::getCustomerId, customerIds)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public int setCustomerInfoTag(List<Long> customerIds, List<Long> tagIds) {
|
|
|
+ if (CollUtil.isEmpty(customerIds) || CollUtil.isEmpty(tagIds)) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ String platform = PlatformContext.getPlatform();
|
|
|
+ this.insertCustomerInfoTag(customerIds, tagIds, false, platform);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void insertCustomerInfoTag(List<Long> customerIdList, List<Long> tagIdList, boolean clear, String platformCode) {
|
|
|
+
|
|
|
+
|
|
|
+ // 1. 如果 clear = true,则删除这些客户在该平台下的所有标签
|
|
|
+ if (clear) {
|
|
|
+ customerInfoTagMapper.delete(
|
|
|
+ new LambdaQueryWrapper<CustomerInfoTag>()
|
|
|
+ .in(CustomerInfoTag::getCustomerId, customerIdList)
|
|
|
+ .eq(CustomerInfoTag::getPlatformCode, platformCode)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 查询这些客户当前已有的(客户ID, 标签ID)组合,避免重复插入
|
|
|
+ List<CustomerInfoTag> existingList = customerInfoTagMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<CustomerInfoTag>()
|
|
|
+ .in(CustomerInfoTag::getCustomerId, customerIdList)
|
|
|
+ .in(CustomerInfoTag::getTagId, tagIdList)
|
|
|
+ .eq(CustomerInfoTag::getPlatformCode, platformCode)
|
|
|
+ );
|
|
|
+
|
|
|
+ // 构建已存在的 (customerId, tagId) 集合,用于去重
|
|
|
+ Set<String> existingPairs = existingList.stream()
|
|
|
+ .map(cit -> cit.getCustomerId() + "_" + cit.getTagId())
|
|
|
+ .collect(Collectors.toSet());
|
|
|
+
|
|
|
+ // 3. 构造需要新增的记录(笛卡尔积:每个客户 × 每个标签)
|
|
|
+ List<CustomerInfoTag> toInsertList = new ArrayList<>();
|
|
|
+ for (Long customerId : customerIdList) {
|
|
|
+ for (Long tagId : tagIdList) {
|
|
|
+ String pair = customerId + "_" + tagId;
|
|
|
+ if (!existingPairs.contains(pair)) {
|
|
|
+ CustomerInfoTag cit = new CustomerInfoTag();
|
|
|
+ cit.setCustomerId(customerId);
|
|
|
+ cit.setTagId(tagId);
|
|
|
+ cit.setPlatformCode(platformCode);
|
|
|
+ toInsertList.add(cit);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 批量插入
|
|
|
+ if (!toInsertList.isEmpty()) {
|
|
|
+ customerInfoTagMapper.insertBatch(toInsertList);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* 保存前的数据校验
|
|
|
*/
|
|
|
- private void validEntityBeforeSave(CustomerInfo entity){
|
|
|
+ private void validEntityBeforeSave(CustomerInfo entity) {
|
|
|
//TODO 做一些数据校验,如唯一约束
|
|
|
}
|
|
|
|
|
|
@@ -357,7 +557,7 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cu
|
|
|
*/
|
|
|
@Override
|
|
|
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
|
|
- if(isValid){
|
|
|
+ if (isValid) {
|
|
|
//TODO 做一些业务上的校验,判断是否需要校验
|
|
|
}
|
|
|
return baseMapper.deleteByIds(ids) > 0;
|