package cn.fw.valhalla.service.bus.cust; import cn.fw.common.exception.BusinessException; import cn.fw.common.page.AppPage; import cn.fw.common.web.annotation.DisLock; import cn.fw.common.web.auth.LoginAuthBean; import cn.fw.valhalla.common.constant.RoleCode; import cn.fw.valhalla.common.utils.BeanUtils; import cn.fw.valhalla.common.utils.DateUtil; import cn.fw.valhalla.domain.db.CompanyWechatJoin; import cn.fw.valhalla.domain.db.MemberVehicle; import cn.fw.valhalla.domain.db.WechatSubscribe; import cn.fw.valhalla.domain.db.customer.*; import cn.fw.valhalla.domain.db.follow.ClueTask; import cn.fw.valhalla.domain.db.follow.FollowClue; import cn.fw.valhalla.domain.db.follow.FollowRecord; import cn.fw.valhalla.domain.db.pool.PublicCluePool; import cn.fw.valhalla.domain.db.pool.PublicPool; import cn.fw.valhalla.domain.db.pool.StammkundePool; import cn.fw.valhalla.domain.db.pub.PubCluePool; import cn.fw.valhalla.domain.dto.CustomerDetailDto; import cn.fw.valhalla.domain.enums.*; import cn.fw.valhalla.domain.query.CustomCustomerQuery; import cn.fw.valhalla.domain.query.CustomerQueryVO; import cn.fw.valhalla.domain.query.StammkundeAnalyseQueryVO; import cn.fw.valhalla.domain.vo.customer.*; import cn.fw.valhalla.domain.vo.setting.SettingVO; import cn.fw.valhalla.rpc.angel.dto.InsuranceDTO; import cn.fw.valhalla.rpc.erp.dto.PostUserDTO; import cn.fw.valhalla.rpc.erp.dto.UserInfoDTO; import cn.fw.valhalla.rpc.erp.dto.UserRoleDataRangeDTO; import cn.fw.valhalla.rpc.member.MemberRpcService; import cn.fw.valhalla.rpc.member.dto.MemberUserDTO; import cn.fw.valhalla.rpc.oop.OopService; import cn.fw.valhalla.rpc.oop.dto.ShopDTO; import cn.fw.valhalla.rpc.oop.dto.SpecDTO; import cn.fw.valhalla.sdk.enums.CusTypeEnum; import cn.fw.valhalla.sdk.param.ChangeSpecCodeReq; import cn.fw.valhalla.sdk.param.CustomerParams; import cn.fw.valhalla.sdk.param.CustomerQueryReq; import cn.fw.valhalla.sdk.result.BasicsCustomerDTO; import cn.fw.valhalla.sdk.result.CustomerInfoDto; import cn.fw.valhalla.sdk.result.MemberVehicleDTO; import cn.fw.valhalla.sdk.result.ReceptionResultDto; import cn.fw.valhalla.service.bus.StammkundeBizService; import cn.fw.valhalla.service.bus.setting.SettingBizService; import cn.fw.valhalla.service.data.*; import cn.fw.valhalla.service.event.PublicPoolEvent; import cn.fw.valhalla.service.event.StopTaskEvent; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; import static cn.fw.common.businessvalidator.Validator.BV; import static cn.fw.common.businessvalidator.Validator.V; import static cn.fw.valhalla.service.bus.setting.strategy.SettingStrategy.COMMON_BRAND_ID; /** * @author : kurisu * @className : CustomerBizService * @description : 档案 * @date: 2020-08-12 13:57 */ @Service @Slf4j @RequiredArgsConstructor public class CustomerBizService extends AbstractCustomerService { /** * 关注公众号服务 */ private final WechatSubscribeService wechatSubscribeService; /** * 加入企业微信服务 */ private final CompanyWechatJoinService companyWechatJoinService; private final MemberRpcService memberRpcService; private final AffiliationRecordService affiliationRecordService; private final PublicPoolService publicPoolService; private final ApplicationEventPublisher eventPublisher; private final CustomerReachLogService customerReachLogService; private final SettingBizService settingBizService; private final FollowRecordService followRecordService; private final StammkundeBizService stammkundeBizService; private final OopService oopService; private final MemberVehicleService memberVehicleService; private final FollowClueService followClueService; @Value("${spring.cache.custom.global-prefix}:customer") @Getter private String keyPrefix; /** * app分页查询档案 * * @param queryVO * @return */ public AppPage getList(CustomerQueryVO queryVO) { queryVO.setCurrent(queryVO.getCurrent() > 0 ? queryVO.getCurrent() : 1); Integer startIndex = (queryVO.getCurrent() - 1) * queryVO.getPageSize(); if (Boolean.TRUE.equals(queryVO.getFromReport())) { StammkundeAnalyseQueryVO analyseQueryVO = new StammkundeAnalyseQueryVO(); analyseQueryVO.setTimeHorizon(queryVO.getTimeHorizon()); analyseQueryVO.setFollowType(queryVO.getFollowType()); analyseQueryVO.setUnderway(queryVO.getUnderway()); analyseQueryVO.setLat(queryVO.getLat()); analyseQueryVO.setLng(queryVO.getLng()); analyseQueryVO.setRadius(queryVO.getRadius()); analyseQueryVO.setGroupId(queryVO.getGroupId()); analyseQueryVO.setShopIds(queryVO.getShopIdStr()); List vos = stammkundeBizService.stammkundeList(analyseQueryVO); if (CollectionUtils.isNotEmpty(vos)) { List longList = vos.stream().map(StammkundeAnalyseVO::getCustomerId).collect(Collectors.toList()); queryVO.setCustomerIdList(longList); } } List appPageList = customerService.getAppPageList(startIndex, queryVO.getPageSize(), queryVO); AppPage page = AppPage.empty(queryVO); page.setData(appPageList); return page; } /** * 根据档案id查询详情 * * @param cusId * @return */ public CustomerDetailVO getDetailById(final Long cusId) { CustomerDetailDto detailDto = queryById(cusId); BV.notNull(detailDto, () -> "查无此档案"); BV.isTrue(detailDto.getYn(), () -> "此档案已经作废,无法再继续查看"); CustomerDetailVO vo = new CustomerDetailVO(); BeanUtils.copyProperties(detailDto, vo); vo.setRealMobile(detailDto.getMobile()); vo.setOrgCode(detailDto.getIdCode()); if (Objects.nonNull(detailDto.getBuyDate())) { LocalDate buyDate = DateUtil.date2LocalDate(detailDto.getBuyDate()); long days = LocalDate.now().toEpochDay() - buyDate.toEpochDay(); double years = Math.ceil(days / 365.0); vo.setAgeLimit(Math.round(years)); } return vo; } /** * 根据vin查询详情 * * @param vin * @param groupId * @return */ public CustomerDetailVO getDetailByVin(final String vin, final Long groupId) { Customer customer = customerService.queryByFrameNo(vin, groupId); BV.notNull(customer, () -> "档案不存在"); CustomerDetailDto detailDto = queryById(customer.getId()); BV.isTrue(detailDto.getYn(), () -> "此档案已经作废,无法再继续查看"); CustomerDetailVO vo = new CustomerDetailVO(); BeanUtils.copyProperties(detailDto, vo); vo.setRealMobile(detailDto.getMobile()); vo.setOrgCode(detailDto.getIdCode()); if (Objects.nonNull(detailDto.getBuyDate())) { LocalDate buyDate = DateUtil.date2LocalDate(detailDto.getBuyDate()); long days = LocalDate.now().toEpochDay() - buyDate.toEpochDay(); double years = Math.ceil(days / 365.0); vo.setAgeLimit(Math.round(years)); } return vo; } /** * 根据ID查询档案基本信息 * * @param id * @return */ public VehicleRecordVO getCarInfoById(Long id) { final VehicleRecordVO vo = new VehicleRecordVO(); Customer customer = customerService.queryById(id); BV.notNull(customer, () -> "查无此档案"); CustomerDetailDto detailDto = renderDto(customer); BeanUtils.copyProperties(detailDto, vo); Optional dtoOptional = queryInsuInfo(customer.getId()); dtoOptional.ifPresent(t -> { vo.setInsurCompanyId(t.getInsurerId()); vo.setInsurCompanyName(t.getInsurerName()); vo.setInsurExpireDate(t.getExpiryDate()); }); if (Objects.nonNull(customer.getBuyDate())) { LocalDate buyDate = DateUtil.date2LocalDate(customer.getBuyDate()); long days = LocalDate.now().toEpochDay() - buyDate.toEpochDay(); double years = Math.ceil(days / 365.0); vo.setAgeLimit(Math.round(years)); } return vo; } /** * 根据id查询车辆所有人信息 * * @param id * @return */ public OwnerVO getOwnerInfo(Long id) { OwnerVO vo = new OwnerVO(); Customer customer = customerService.queryById(id); BV.notNull(customer, "查无此档案"); CustomerDetailDto detailDto = renderDto(customer); BeanUtils.copyProperties(detailDto, vo); vo.setIdNum(detailDto.getIdCode()); vo.setId(id); // 是否关注微信公众号 vo.setSubscribed(wechatSubscribeService.count(Wrappers.lambdaQuery() .eq(WechatSubscribe::getSubscribed, Boolean.TRUE) .eq(WechatSubscribe::getMemberId, detailDto.getMemberId())) > 0); vo.setJoined(companyWechatJoinService.count(Wrappers.lambdaQuery() .eq(CompanyWechatJoin::getJoined, Boolean.TRUE) .eq(CompanyWechatJoin::getMemberId, detailDto.getMemberId())) > 0); return vo; } /** * 根据memberId查询该客户的更多车辆 * * @param id * @param groupId * @return */ public List getMoreArchive(Long id, Long groupId) { Customer customer = customerService.queryById(id); if (Objects.isNull(customer)) { return new ArrayList<>(); } List list = new ArrayList<>(); List customerList = customerService.getBaseMapper().selectList(Wrappers.lambdaQuery() .eq(Customer::getBaseId, customer.getBaseId()) .ne(Customer::getId, customer.getId()) .eq(Customer::getGroupId, groupId) .eq(Customer::getYn, Boolean.TRUE) ); if (!CollectionUtils.isEmpty(customerList)) { for (Customer cust : customerList) { MoreVehicleVO vo = new MoreVehicleVO(); BeanUtils.copyProperties(cust, vo); vo.setId(cust.getId()); list.add(vo); } } return list; } /** * 批量查询保有客档案 * * @param customerIds 保有客档案id集合 * @return 保有客档案 */ public List queryBatch(final Long[] customerIds) { final List customers = customerService.list(Wrappers.lambdaQuery() .in(Customer::getId, Arrays.asList(customerIds))); if (CollectionUtils.isEmpty(customers)) { return Collections.emptyList(); } List baseIdList = customers.stream().filter(i -> Objects.nonNull(i.getBaseId())) .map(Customer::getBaseId).distinct().collect(Collectors.toList()); final List customerBaseInfoList = customerBaseInfoService.listByIds(baseIdList); Map baseInfoMap = customerBaseInfoList.stream() .collect(Collectors.toMap(CustomerBaseInfo::getId, CustomerBaseInfo::getMemberId)); return customers.stream().map(customer -> { CustomerInfoDto customerInfoDto = new CustomerInfoDto(); BeanUtils.copyProperties(customer, customerInfoDto); customerInfoDto.setId(customer.getId()); if (Objects.nonNull(customer.getBaseId())) { customerInfoDto.setMemberId(baseInfoMap.getOrDefault(customer.getBaseId(), null)); } customerInfoDto.setCreateTime(customer.getCreateTime()); customerInfoDto.setConsultantId(customer.getAdviserId()); return customerInfoDto; }).collect(Collectors.toList()); } /** * 查询会员对应保有客的商家id * * @param memberId 会员id * @param groupId 集团id * @return 商家id集合 */ public List getCustomerDealerId(Long groupId, Long memberId) { CustomerBaseInfo baseInfo = customerBaseInfoService.getOne(Wrappers.lambdaQuery() .eq(CustomerBaseInfo::getGroupId, groupId) .eq(CustomerBaseInfo::getMemberId, memberId) .eq(CustomerBaseInfo::getYn, Boolean.TRUE) .last("limit 1") ); if (Objects.isNull(baseInfo)) { return Collections.emptyList(); } final List customers = customerService.list(Wrappers.lambdaQuery() .eq(Customer::getGroupId, groupId) .eq(Customer::getBaseId, baseInfo.getId()) .eq(Customer::getYn, Boolean.TRUE) ); if (CollectionUtils.isEmpty(customers)) { return Collections.emptyList(); } return customers.stream().map(Customer::getShopId).distinct().collect(Collectors.toList()); } /** * 修改车型代码 * * @param customerId * @param specCode * @return * @deprecated */ @Deprecated public boolean modifySpecCode(Long customerId, String specCode) { Customer customer = customerService.queryById(customerId); BV.notNull(customer, () -> "档案不存在"); customer.setSpecCode(specCode); return customerService.updateById(customer); } /** * 修改车型代码 * * @param req * @return */ public boolean fixSpecCode(ChangeSpecCodeReq req) { Customer customer = customerService.queryById(req.getCustomerId()); BV.notNull(customer, () -> "档案不存在"); customer.setBrandId(req.getBrandId()); customer.setBrandName(req.getBrandName()); customer.setSeriesId(req.getSeriesId()); customer.setSeriesName(req.getSeriesName()); customer.setSpecId(req.getSpecId()); customer.setSpecName(req.getSpecName()); customer.setSpecCode(req.getSpecCode()); return customerService.updateById(customer); } /** * 查询能否接车 * * @param userId * @param plateNo * @return */ public ReceptionResultDto queryReceivable(Long userId, String plateNo) { UserInfoDTO userInfo = ehrRpcService.user(userId); if (Objects.isNull(userInfo)) { return new ReceptionResultDto(false, "非服务顾问无法接待"); } List dataRange = userService.getUserRoleDataRange(userId, RoleCode.FWGW); if (CollectionUtils.isEmpty(dataRange)) { return new ReceptionResultDto(false, "非服务顾问无法接待"); } Customer customer = customerService.queryByPlateNo(plateNo, userInfo.getGroupId()); if (Objects.isNull(customer)) { return new ReceptionResultDto(true, ""); } ShopDTO shop = oopService.shop(dataRange.get(0).getRangeValue()); if (Objects.isNull(shop)) { return new ReceptionResultDto(false, "服务顾问服务站信息不正确"); } boolean bool = affiliationRecordService.count(Wrappers.lambdaQuery() .eq(AffiliationRecord::getType, CustomerChangeTypeEnum.DEFEAT) .eq(AffiliationRecord::getOriginUserId, userId) .eq(AffiliationRecord::getCustomerId, customer.getId()) .ge(AffiliationRecord::getDefeatTime, DateUtil.getNowExpiredMonth(-12)) ) > 0; if (bool) { return new ReceptionResultDto(false, "无法接待由你战败的客户"); } return new ReceptionResultDto(true, ""); } public List queryIllegalAdviser(Long cusId) { List list = affiliationRecordService.list(Wrappers.lambdaQuery() .eq(AffiliationRecord::getType, CustomerChangeTypeEnum.DEFEAT) .eq(AffiliationRecord::getCustomerId, cusId) .ge(AffiliationRecord::getDefeatTime, DateUtil.getNowExpiredMonth(-12))); if (CollectionUtils.isEmpty(list)) { return Collections.emptyList(); } return list.stream().map(AffiliationRecord::getOriginUserId).distinct().collect(Collectors.toList()); } /** * 根据档案id查询详情 * * @param cusId * @return */ public CustomerDetailDto queryById(final Long cusId) { Customer customer = customerService.queryById(cusId); if (Objects.isNull(customer)) { return null; } return renderDto(customer); } /** * 根据自定义条件查询保有客档案 * 市场活动用 * * @param queryReq * @return */ public List queryCustomList(final CustomerQueryReq queryReq) { CustomCustomerQuery query = fillParams(queryReq); return customerService.queryCustomList(query); } /** * 根据自定义条件查询保有客档案数量 * * @param queryReq * @return */ public Long queryCustomCount(final CustomerQueryReq queryReq) { CustomCustomerQuery query = fillParams(queryReq); return customerService.queryCustomListCount(query); } /** * 根据手机号查询所有档案 * * @param mobile * @param groupId * @return */ public List queryByMobile(final String mobile, final Long groupId) { CustomerBaseInfo baseInfo = customerBaseInfoService.queryByMobile(mobile, groupId); if (Objects.isNull(baseInfo)) { return new ArrayList<>(); } List customerList = customerService.queryByBaseId(baseInfo.getId()); if (CollectionUtils.isEmpty(customerList)) { return new ArrayList<>(); } List list = new ArrayList<>(); for (Customer customer : customerList) { list.add(renderDto(customer, baseInfo)); } return list; } /** * 放弃客户 * * @param customerId * @param reason */ @Transactional(rollbackFor = Exception.class) public void abandon(final Long customerId, final String reason) { CustomerDetailDto detailDto = queryById(customerId); BV.notNull(detailDto, () -> "档案不存在"); PublicPool publicData = publicPoolService.queryByVin(detailDto.getFrameNo(), detailDto.getGroupId()); if (Objects.nonNull(publicData)) { return; } PublicPool publicPool = createPublicPool(detailDto, PublicPoolTypeEnum.AD, reason); boolean updated = customerService.update(Wrappers.lambdaUpdate() .set(Customer::getAdviserId, null) .set(Customer::getShopId, null) .eq(Customer::getId, customerId)); if (!updated) { return; } AffiliationRecord entity = createEntity(detailDto); entity.setReason(DefeatReasonEnum.GU.getName()); affiliationRecordService.save(entity); publicPoolService.save(publicPool); stammkundePoolService.reject(customerId, detailDto.getGroupId(), DefeatReasonEnum.GU); publicCluePoolService.removeClue(customerId, detailDto.getAdviserId()); PublicPoolEvent poolEvent = new PublicPoolEvent(detailDto.getFrameNo(), detailDto.getGroupId()); eventPublisher.publishEvent(poolEvent); } /** * 审批通过客户档案处理 * * @param task */ @Transactional(rollbackFor = Exception.class) public void abandon(final ClueTask task) { List typeList = Arrays.asList(FollowTypeEnum.AC, FollowTypeEnum.IR); HashSet set = new HashSet<>(typeList); if (set.contains(task.getType())) { StopTaskEvent stopTaskEvent = new StopTaskEvent(task); eventPublisher.publishEvent(stopTaskEvent); return; } FollowClue followClue = followClueService.getById(task.getClueId()); if (Objects.isNull(followClue)) { return; } CustomerDetailDto detailDto = queryByFrameNo(followClue.getVin(), followClue.getGroupId()); if (Objects.isNull(detailDto)) { return; } PublicPoolTypeEnum type = PublicPoolTypeEnum.FM; if (FollowTypeEnum.RM.equals(task.getType())) { type = PublicPoolTypeEnum.RM; } abandon(detailDto.getFrameNo(), detailDto.getGroupId(), type); } /** * 审批通过客户档案处理 * * @param vin * @param groupId * @param type */ @Transactional(rollbackFor = Exception.class) public void abandon(String vin, final Long groupId, PublicPoolTypeEnum type) { CustomerDetailDto detailDto = queryByFrameNo(vin, groupId); if (Objects.isNull(detailDto)) { return; } PublicPool publicData = publicPoolService.queryByVin(detailDto.getFrameNo(), detailDto.getGroupId()); if (Objects.nonNull(publicData)) { return; } PublicPool publicPool = createPublicPool(detailDto, type, "系统判定"); boolean updated = customerService.update(Wrappers.lambdaUpdate() .set(Customer::getAdviserId, null) .set(Customer::getShopId, null) .eq(Customer::getId, detailDto.getId())); if (!updated) { return; } AffiliationRecord entity = createEntity(detailDto); entity.setReason(DefeatReasonEnum.GU.getName()); affiliationRecordService.save(entity); publicPoolService.save(publicPool); stammkundePoolService.reject(detailDto.getId(), groupId, DefeatReasonEnum.GU); publicCluePoolService.removeClue(detailDto.getId(), detailDto.getAdviserId()); PublicPoolEvent poolEvent = new PublicPoolEvent(detailDto.getFrameNo(), groupId); eventPublisher.publishEvent(poolEvent); } /** * 任务结束战败客户到公共池 * * @param task * @param followClue */ @Transactional(rollbackFor = Exception.class) public void taskEndAbandon(final ClueTask task, final FollowClue followClue) { CustomerDetailDto detailDto = queryByFrameNo(followClue.getVin(), followClue.getGroupId()); if (Objects.isNull(detailDto)) { return; } PublicPoolTypeEnum type = PublicPoolTypeEnum.FM; if (FollowTypeEnum.RM.equals(task.getType())) { type = PublicPoolTypeEnum.RM; } boolean updated = customerService.update(Wrappers.lambdaUpdate() .set(Customer::getAdviserId, null) .set(Customer::getShopId, null) .set(Customer::getTemporary, null) .eq(Customer::getId, detailDto.getId())); if (!updated) { return; } stammkundePoolService.reject(detailDto.getId(), task.getGroupId(), FollowTypeEnum.RM.equals(task.getType()) ? DefeatReasonEnum.RM : DefeatReasonEnum.FM); publicCluePoolService.removeClue(detailDto.getId(), detailDto.getAdviserId()); AffiliationRecord entity = createEntity(detailDto); entity.setReason("跟进超期"); if (Objects.isNull(entity.getOriginUserId())) { entity.setOriginUserId(task.getFollowUser()); } if (Objects.isNull(entity.getOriginShopId())) { entity.setOriginShopId(task.getFollowShop()); } affiliationRecordService.save(entity); PublicPool publicData = publicPoolService.queryByVin(detailDto.getFrameNo(), detailDto.getGroupId()); if (Objects.nonNull(publicData)) { return; } PublicPool publicPool = createPublicPool(detailDto, type, "跟进超期"); publicPoolService.save(publicPool); } /** * 公共池跟进任务结束战败客户到公共池 * * @param pubCluePool */ @Transactional(rollbackFor = Exception.class) public void pubTaskEndAbandon(PubCluePool pubCluePool) { Long groupId = pubCluePool.getGroupId(); CustomerDetailDto detailDto = queryByFrameNo(pubCluePool.getVin(), groupId); if (Objects.isNull(detailDto)) { return; } boolean updated = customerService.update(Wrappers.lambdaUpdate() .set(Customer::getAdviserId, null) .set(Customer::getShopId, null) .set(Customer::getTemporary, null) .eq(Customer::getId, detailDto.getId())); if (!updated) { return; } stammkundePoolService.reject(detailDto.getId(), groupId, DefeatReasonEnum.CD); publicCluePoolService.removeClue(detailDto.getId(), detailDto.getAdviserId()); AffiliationRecord entity = createEntity(detailDto); entity.setReason("跟进超期"); affiliationRecordService.save(entity); PublicPool publicData = publicPoolService.queryByVin(detailDto.getFrameNo(), detailDto.getGroupId()); if (Objects.nonNull(publicData)) { return; } PublicPool publicPool = createPublicPool(detailDto, PublicPoolTypeEnum.PD, PublicPoolTypeEnum.PD.getName()); publicPoolService.save(publicPool); } /** * 继续跟进 * * @param currentUser * @param customerId * @deprecated */ @DisLock(prefix = "#this.getKeyPrefix()", key = "'continueFollow:' + #customerId", message = "请勿重复提交") public void continueFollow(LoginAuthBean currentUser, final Long customerId) { List dataRange = userService.getUserRoleDataRange(currentUser.getUserId(), RoleCode.FWGW); BV.isFalse(CollectionUtils.isEmpty(dataRange), () -> "非服务顾问无法进行操作"); Customer customer = customerService.queryById(customerId); if (Objects.isNull(customer)) { publicPoolService.removeByCustomerId(customerId, currentUser.getGroupId()); throw new BusinessException("档案信息有误,请刷新后重试"); } boolean bool = affiliationRecordService.count(Wrappers.lambdaQuery() .eq(AffiliationRecord::getType, CustomerChangeTypeEnum.DEFEAT) .eq(AffiliationRecord::getOriginUserId, currentUser.getUserId()) .eq(AffiliationRecord::getCustomerId, customerId) ) > 0; BV.isFalse(bool, () -> "无法继续跟进由你战败的客户"); Optional voOptional = settingBizService.querySettingByType(FollowTypeEnum.OT, SettingTypeEnum.PUBLIC_VALID_DAY, currentUser.getGroupId(), COMMON_BRAND_ID); SettingVO settingVO = voOptional.orElse(null); BV.notNull(settingVO, () -> "设置获取失败"); UserRoleDataRangeDTO rangeDTO = dataRange.get(0); publicPoolService.removeByCustomerId(customerId, currentUser.getGroupId()); if (Objects.isNull(customer.getAdviserId()) && Objects.isNull(customer.getShopId())) { Date deadline = DateUtil.localDateTime2Date(LocalDate.now().plusDays(settingVO.getDetailValue()).atStartOfDay()); createPublicPoolClue(customer, currentUser, rangeDTO, deadline); } } /** * 根据车牌号查询所有档案 * * @param plateNo * @param groupId * @return */ public CustomerDetailDto queryByPlateNo(final String plateNo, final Long groupId) { Customer customer = customerService.queryByPlateNo(plateNo, groupId); if (Objects.isNull(customer)) { return null; } return renderDto(customer); } /** * 根据车架号号查询所有档案 * * @param frameNo * @param groupId * @return */ public CustomerDetailDto queryByFrameNo(final String frameNo, final Long groupId) { Customer customer = customerService.queryByFrameNo(frameNo, groupId); if (Objects.isNull(customer)) { return null; } return renderDto(customer); } /** * 根据车架号号查询车辆信息 * * @param frameNo 车架号 * @param shopId 门店id * @return 车辆信息 */ public CustomerDetailDto queryVehicleByFrameNo(final String frameNo, final Long shopId) { ShopDTO shop = oopService.shop(shopId); V.notNull(shop, String.format("未查询到门店%d信息", shopId)); Customer customer = customerService.queryByFrameNo(frameNo, shop.getGroupId()); if (Objects.isNull(customer)) { MemberVehicle memberVehicle = memberVehicleService.getVehicle(frameNo); if (Objects.isNull(memberVehicle)) { return null; } if (CusTypeEnum.PERSONAL.equals(memberVehicle.getCusType())) { //查询该会员的其他车辆是否有档案 List customerBaseInfoList = customerBaseInfoService .list(Wrappers.lambdaQuery() .eq(CustomerBaseInfo::getYn, Boolean.TRUE) .eq(CustomerBaseInfo::getCusType, CusTypeEnum.PERSONAL) .eq(CustomerBaseInfo::getMemberId, memberVehicle.getMemberId())) .stream().map(CustomerBaseInfo::getId).collect(Collectors.toList()); if (CollectionUtils.isEmpty(customerBaseInfoList)) { return CustomerDetailDto.with(memberVehicle); } final List customers = customerService.list(Wrappers.lambdaQuery() .in(Customer::getBaseId, customerBaseInfoList).eq(Customer::getYn, true) .eq(Customer::getGroupId, shop.getGroupId()).eq(Customer::getShopId, shopId) .isNotNull(Customer::getAdviserId) .orderByDesc(Customer::getUpdateTime)); if (CollectionUtils.isEmpty(customers)) { return CustomerDetailDto.with(memberVehicle); } CustomerDetailDto dto = CustomerDetailDto.with(memberVehicle); dto.setAdviserId(customers.get(0).getAdviserId()); UserInfoDTO user = ehrRpcService.user(customers.get(0).getAdviserId()); if (Objects.nonNull(user)) { dto.setAdviserName(user.getUserName()); } return dto; } else { //查询该单位是否有其他档案 List customerBaseInfoList = customerBaseInfoService .list(Wrappers.lambdaQuery() .eq(CustomerBaseInfo::getYn, Boolean.TRUE) .eq(CustomerBaseInfo::getCusType, CusTypeEnum.COMPANY) .eq(CustomerBaseInfo::getName, memberVehicle.getName())) .stream().map(CustomerBaseInfo::getId).collect(Collectors.toList()); if (CollectionUtils.isEmpty(customerBaseInfoList)) { return CustomerDetailDto.with(memberVehicle); } final List customers = customerService.list(Wrappers.lambdaQuery() .in(Customer::getBaseId, customerBaseInfoList).eq(Customer::getYn, true) .eq(Customer::getGroupId, shop.getGroupId()).eq(Customer::getShopId, shopId) .isNotNull(Customer::getAdviserId) .orderByDesc(Customer::getUpdateTime)); if (CollectionUtils.isEmpty(customers)) { return CustomerDetailDto.with(memberVehicle); } CustomerDetailDto dto = CustomerDetailDto.with(memberVehicle); dto.setAdviserId(customers.get(0).getAdviserId()); UserInfoDTO user = ehrRpcService.user(customers.get(0).getAdviserId()); if (Objects.nonNull(user)) { dto.setAdviserName(user.getUserName()); } return dto; } } CustomerDetailDto dto = renderDto(customer); if (!Objects.equals(customer.getShopId(), shopId)) { dto.setShopId(null); dto.setAdviserId(null); dto.setAdviserName(null); } if (Objects.nonNull(customer) && Objects.isNull(customer.getRegDate())) { MemberVehicle memberVehicle = memberVehicleService.getVehicle(frameNo); customer.setRegDate(Objects.nonNull(memberVehicle) ? memberVehicle.getRegDate() : null); } return dto; } /** * 根据发动机号查询所有档案 * * @param engineNo * @param groupId * @return */ public CustomerDetailDto queryByEngineNo(final String engineNo, final Long groupId) { Customer customer = customerService.queryByEngineNo(engineNo, groupId); if (Objects.isNull(customer)) { return null; } return renderDto(customer); } /** * 是否关联了档案 * * @param customerParams * @return */ @Transactional(rollbackFor = Exception.class) public Boolean save4api(final CustomerParams customerParams) { final String plateNo = customerParams.getPlateNo(); final String frameNo = customerParams.getFrameNo(); final Long groupId = customerParams.getGroupId(); Customer customer = customerService.queryByPlateNo(plateNo, groupId); BV.isNull(customer, "该车牌号对应的档案已存在"); customer = customerService.queryByFrameNo(frameNo, groupId); BV.isNull(customer, "该车辆已存在档案"); CustomerBaseInfo baseInfo = new CustomerBaseInfo(); BeanUtils.copyProperties(customerParams, baseInfo); baseInfo.setContact(customerParams.getName()); baseInfo.setYn(Boolean.TRUE); baseInfo.setCreateTime(new Date()); baseInfo.setUpdateTime(new Date()); customer = new Customer(); ShopDTO shop = oopService.shop(customerParams.getShopId()); BV.notNull(shop, () -> "shop信息有误,请检查"); Long casShopId = shop.getCasShopId(); Long adviserId = customerParams.getAdviserId(); List userByRole = userService.getUserByRole(casShopId, RoleCode.FWGW); BV.isNotEmpty(userByRole, () -> "门店暂无服务顾问,无法新增档案"); boolean match = userByRole.stream().anyMatch(u -> u.getUserId().equals(adviserId)); if (!match) { Long newUserId = userByRole.parallelStream().findAny().map(PostUserDTO::getUserId).orElse(-1L); BV.isTrue(newUserId > 0 && !newUserId.equals(adviserId), () -> "服务顾问获取失败"); customerParams.setAdviserId(newUserId); } BeanUtils.copyProperties(customerParams, customer); customer.setSpecCode(customerParams.getSpecCode()); customer.setCreateTime(new Date()); customer.setUpdateTime(new Date()); customer.setYn(Boolean.TRUE); customer.setTemporary(Boolean.FALSE); final SpecDTO spec = oopService.spec(customerParams.getSpecId()); customer.setCarImage(Optional.ofNullable(spec).orElse(new SpecDTO()).getThumbnail()); customer.setShopId(casShopId); Long cid = saveNewOne(customer, baseInfo, true); CustomerParams.LoanInfo loanInfo = customerParams.getLoanInfo(); if (Objects.nonNull(loanInfo)) { saveLoanInfo(customer.getGroupId(), customer.getFrameNo(), loanInfo.getPeriods(), loanInfo.getExpires()); } return Objects.nonNull(cid); } /** * 更新购车日期 * * @param vin * @param date * @param groupId */ @Transactional(rollbackFor = Exception.class) public void updateCustomerBuyDate(final String vin, final Date date, final Long groupId) { Customer customer = customerService.queryByFrameNo(vin, groupId); if (Objects.isNull(customer)) { return; } customer.setBuyDate(date); customerService.updateById(customer); } public List memberCarList(final Long memberId, final Long groupId) { BV.notNull(groupId, () -> "集团ID不能为空"); List list = this.defaultCustomer(memberId); if (CollectionUtils.isEmpty(list)) { return list; } return list.stream().filter(r -> Objects.equals(r.getGroupId(), groupId)).collect(Collectors.toList()); } /** * 查询所有字段 * * @param memberId * @return */ public List defaultCustomer(final Long memberId) { if (Objects.isNull(memberId)) { return new ArrayList<>(); } final MemberUserDTO user = memberRpcService.user(memberId); if (Objects.isNull(user)) { return new ArrayList<>(); } List baseList = this.customerBaseInfoService.list(Wrappers.lambdaQuery() .eq(CustomerBaseInfo::getMemberId, memberId) .eq(CustomerBaseInfo::getYn, Boolean.TRUE) ); List baseIds = Optional.ofNullable(baseList).map(l -> l.stream().map(CustomerBaseInfo::getId).collect(Collectors.toList())).orElse(null); if (CollectionUtils.isEmpty(baseIds)) { return new ArrayList<>(); } final List customers = this.customerService.list(Wrappers.lambdaQuery() .in(Customer::getBaseId, baseIds) .eq(Customer::getYn, Boolean.TRUE) .orderByDesc(Customer::getCreateTime)); if (CollectionUtils.isNotEmpty(customers)) { return customers.stream() .map(CarArchiveVO::with) .filter(Objects::nonNull) .peek(vo -> { UserInfoDTO dto = ehrRpcService.user(vo.getAdviserId()); if (Objects.nonNull(dto)) { vo.setAdviserName(dto.getUserName()); } ShopDTO shop = oopService.shop(vo.getShopId()); if (Objects.nonNull(shop)) { vo.setShopName(shop.getShortName()); } vo.setDealerInfoVO(createDeal(vo.getShopId())); vo.setOwner(true); vo.setOwnerName(user.getRealName()); loanCustomer(vo); }).collect(Collectors.toList()); } return new ArrayList<>(); } /** * @param customer * @param currentUser * @param rangeDTO * @param deadline * @deprecated 已弃用 sclie 2.0 */ @Transactional(rollbackFor = Exception.class) public void createPublicPoolClue(Customer customer, LoginAuthBean currentUser, UserRoleDataRangeDTO rangeDTO, Date deadline) { customer.setAdviserId(currentUser.getUserId()); customer.setShopId(rangeDTO.getRangeValue()); customerService.updateById(customer); StammkundePool stammkundePool = createSimpleInfo(customer); stammkundePool.setAdviserId(currentUser.getUserId()); stammkundePool.setAdviserName(currentUser.getUserName()); stammkundePool.setSources(StammkundeSourcesEnum.PUBLIC_POOL); stammkundePool.setPoolStatus(StammkundeStatusEnum.PUBLIC); stammkundePoolService.save(stammkundePool); createPublicCluePool(customer.getId(), deadline, currentUser, rangeDTO); } /** * 创建公共池线索跟进 * * @param customerId * @param deadline * @param currentUser * @param rangeDTO * @deprecated 已弃用 sclie 2.0 */ private void createPublicCluePool(Long customerId, Date deadline, LoginAuthBean currentUser, UserRoleDataRangeDTO rangeDTO) { final PublicCluePool publicCluePool = new PublicCluePool(); publicCluePool.setCustomerId(customerId); publicCluePool.setDeadline(deadline); publicCluePool.setState(PublicClueStateEnum.ONGOING); publicCluePool.setAdviserId(currentUser.getUserId()); publicCluePool.setAdviserName(currentUser.getUserName()); publicCluePool.setShopId(rangeDTO.getRangeValue()); publicCluePool.setShopName(rangeDTO.getRangeName()); ShopDTO shop = oopService.shop(rangeDTO.getRangeValue()); if (Objects.nonNull(shop)) { publicCluePool.setShopName(shop.getShortName()); } publicCluePool.setGroupId(currentUser.getGroupId()); publicCluePoolService.save(publicCluePool); final FollowRecord record = new FollowRecord(); record.setTaskId(publicCluePool.getId()); record.setCustomerId(publicCluePool.getCustomerId()); record.setType(FollowTypeEnum.OT); record.setUserId(publicCluePool.getAdviserId()); record.setUserName(publicCluePool.getAdviserName()); Date planTime = DateUtil.localDateTime2Date(LocalDateTime.now()); record.setPlanTime(planTime); record.setAddTodo(Boolean.TRUE); record.setDeadline(publicCluePool.getDeadline()); record.setOutTime(Boolean.FALSE); record.setGroupId(publicCluePool.getGroupId()); record.setShopId(publicCluePool.getShopId()); record.setCreateTime(DateUtil.localDateTime2Date(LocalDateTime.now())); followRecordService.save(record); } /** * 创建公共池对象 * * @param dto * @param type * @param reason * @return */ public PublicPool createPublicPool(CustomerDetailDto dto, PublicPoolTypeEnum type, String reason) { PublicPool pool = new PublicPool(); pool.setCustomerId(dto.getId()); pool.setCustomerName(dto.getName()); pool.setPlateNo(dto.getPlateNo()); pool.setFrameNo(dto.getFrameNo()); pool.setBrandId(dto.getBrandId()); pool.setBrandName(dto.getBrandName()); pool.setSeriesId(dto.getSeriesId()); pool.setSeriesName(dto.getSeriesName()); pool.setSpecId(dto.getSpecId()); pool.setSpecName(dto.getSpecName()); pool.setAddress(dto.getAddress()); pool.setCompany(dto.getCompanyName()); pool.setType(type); pool.setReason(reason); Long shopId = Optional.ofNullable(dto.getLastArrivalShop()).orElse(dto.getShopId()); pool.setShopId(shopId); ShopDTO shop = oopService.shop(shopId); if (Objects.nonNull(shop)) { pool.setShopName(shop.getShortName()); } int times = customerReachLogService.count(Wrappers.lambdaQuery() .eq(CustomerReachLog::getFrameNo, dto.getFrameNo()) ); pool.setTimes(times); pool.setGroupId(dto.getGroupId()); return pool; } /** * 档案批量移动到公共池 * * @param customerIdList */ @Transactional(rollbackFor = Exception.class) public void move2PublicPool(List customerIdList) { if (CollectionUtils.isEmpty(customerIdList)) { return; } customerService.update(Wrappers.lambdaUpdate() .set(Customer::getAdviserId, null) .set(Customer::getShopId, null) .set(Customer::getTemporary, null) .in(Customer::getId, customerIdList)); } /** * 档案批量移动到公共池 * * @param customerId */ @Transactional(rollbackFor = Exception.class) public void move2PublicPool(Long customerId) { customerService.update(Wrappers.lambdaUpdate() .set(Customer::getAdviserId, null) .set(Customer::getShopId, null) .set(Customer::getTemporary, null) .eq(Customer::getId, customerId)); } public List queryByKeyword(String keyword, Long groupId) { List list = fromCustomer(keyword, groupId); if (CollectionUtils.isNotEmpty(list)) { return list; } return fromVehicle(keyword); } private List fromCustomer(String keyword, Long groupId) { List list = customerService.queryByKeyword(keyword, groupId); for (BasicsCustomerDTO dto : list) { UserInfoDTO user = ehrRpcService.user(dto.getAdviserId()); if (Objects.nonNull(user)) { dto.setAdviserName(user.getUserName()); } ShopDTO shop = oopService.shop(dto.getShopId()); if (Objects.nonNull(shop)) { dto.setShopName(shop.getShortName()); } } return list; } private List fromVehicle(String keyword) { return memberVehicleService.queryByKeyword(keyword); } public List queryVehicleByMemberId(Long memberId) { List memberVehicleList = memberVehicleService.getMemberVehicle(memberId); if (CollectionUtils.isEmpty(memberVehicleList)) { return Collections.emptyList(); } return memberVehicleList.stream().map(v -> { MemberVehicleDTO dto = BeanUtils.copy(v, MemberVehicleDTO.class); dto.setCusType(v.getCusType().getValue()); dto.setUseType(v.getUseType().getValue()); return dto; }).collect(Collectors.toList()); } public MemberVehicleDTO queryVehicleByVin(String vin) { MemberVehicle memberVehicle = memberVehicleService.getVehicle(vin); if (Objects.isNull(memberVehicle)) { return null; } MemberVehicleDTO dto = BeanUtils.copy(memberVehicle, MemberVehicleDTO.class); dto.setCusType(memberVehicle.getCusType().getValue()); dto.setUseType(memberVehicle.getUseType().getValue()); MemberUserDTO member = memberRpcService.user(memberVehicle.getMemberId()); dto.setMemberPhone(Objects.nonNull(member) ? member.getPhone() : null); return dto; } private AffiliationRecord createEntity(CustomerDetailDto customer) { AffiliationRecord record = new AffiliationRecord(); record.setCustomerId(customer.getId()); record.setType(CustomerChangeTypeEnum.DEFEAT); record.setDefeatTime(DateUtil.localDateTime2Date(LocalDateTime.now())); record.setOriginUserId(customer.getAdviserId()); record.setOriginShopId(customer.getShopId()); record.setCreateTime(DateUtil.localDateTime2Date(LocalDateTime.now())); return record; } private CarArchiveVO.DealerItem createDeal(Long shopId) { //没有商家这个概念 这里主要是兼容之前的小程序代码 ShopDTO shop = oopService.shop(shopId); if (Objects.isNull(shop)) { return null; } CarArchiveVO.DealerItem vo = CarArchiveVO.createDealerItem(); vo.setId(shop.getDealerId()); vo.setName(shop.getDealerName()); vo.setLogo(shop.getShopLogo()); vo.setPhone(shop.getTel()); vo.setAddr(shop.getAddr()); vo.setLat(shop.getLat()); vo.setLng(shop.getLng()); vo.setDistance(0.0); return vo; } private void saveLoanInfo(Long groupId, String vin, int periods, Date expires) { try { CustomerLoanInfo loanInfo = customerLoanInfoService.getOne(Wrappers.lambdaQuery() .eq(CustomerLoanInfo::getFrameNo, vin) .eq(CustomerLoanInfo::getGroupId, groupId) .last(" limit 1") ); if (Objects.nonNull(loanInfo)) { return; } loanInfo = new CustomerLoanInfo(); loanInfo.setFrameNo(vin); loanInfo.setPeriods(periods); loanInfo.setExpires(expires); loanInfo.setGroupId(groupId); customerLoanInfoService.save(loanInfo); } catch (Exception e) { log.error("新增客户贷款信息失败:", e); } } private void loanCustomer(CarArchiveVO vo) { CustomerLoanInfo loanInfo = customerLoanInfoService.getOne(Wrappers.lambdaQuery() .eq(CustomerLoanInfo::getGroupId, vo.getGroupId()) .eq(CustomerLoanInfo::getFrameNo, vo.getFrameNo()) .last(" limit 1 ") ); if (Objects.nonNull(loanInfo)) { vo.setLoanCustomer(LocalDate.now().isBefore(DateUtil.date2LocalDate(loanInfo.getExpires()))); vo.setExpires(loanInfo.getExpires()); vo.setPeriods(loanInfo.getPeriods()); } } private CustomCustomerQuery fillParams(final CustomerQueryReq queryReq) { BV.notNull(queryReq.getGroupId(), () -> "集团id不能为空"); CustomCustomerQuery query = new CustomCustomerQuery(); BeanUtils.copyProperties(queryReq, query); query.setIncludePublic(Boolean.TRUE.equals(queryReq.getIncludePublic())); if (queryReq.getArrivalMileage() != null && queryReq.getArrivalMileage().length > 0) { for (int i = 0; i < queryReq.getArrivalMileage().length; i++) { if (i == 0) { query.setMinMileage(queryReq.getArrivalMileage()[i]); } if (i == 1) { query.setMaxMileage(queryReq.getArrivalMileage()[i]); } } } if (queryReq.getAgeLimit() != null && queryReq.getAgeLimit().length > 0) { for (int i = 0; i < queryReq.getAgeLimit().length; i++) { if (i == 0) { query.setMaxBuyDate(LocalDate.now().plusYears(-1L * queryReq.getAgeLimit()[i])); } if (i == 1) { query.setMinBuyDate(LocalDate.now().plusYears(-1L * queryReq.getAgeLimit()[i])); } } } if (Objects.nonNull(queryReq.getFollowType())) { query.setFollowType(queryReq.getFollowType().getValue()); } boolean b = (Objects.nonNull(query.getMinMileage()) && Objects.nonNull(query.getMaxMileage())) || (Objects.nonNull(query.getMinBuyDate()) && Objects.nonNull(query.getMaxBuyDate())) || Objects.nonNull(query.getLevel()); if (!b) { query.setAndCondition(true); } return query; } }