package com.doumee.service.business.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
import com.doumee.core.exception.BusinessException;
|
import com.doumee.core.model.LoginUserInfo;
|
import com.doumee.core.utils.Constants;
|
import com.doumee.core.utils.Utils;
|
import com.doumee.dao.business.*;
|
import com.doumee.dao.business.dto.YwCustomerGsConfigDTO;
|
import com.doumee.dao.business.model.*;
|
import com.doumee.service.business.YwCustomerDeviceAutoBindService;
|
import com.doumee.service.business.YwCustomerRechargeBizService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.context.annotation.Lazy;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.util.CollectionUtils;
|
|
import java.math.BigDecimal;
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
@Service
|
@Slf4j
|
public class YwCustomerDeviceAutoBindServiceImpl implements YwCustomerDeviceAutoBindService {
|
|
private static final int BIND_SOURCE_CONTRACT = 1;
|
|
@Autowired
|
private YwContractMapper ywContractMapper;
|
@Autowired
|
private YwContractRoomMapper ywContractRoomMapper;
|
@Autowired
|
private YwElectricalRoomMapper ywElectricalRoomMapper;
|
@Autowired
|
private YwCustomerElectricalMapper ywCustomerElectricalMapper;
|
@Autowired
|
private YwCustomerConditionerMapper ywCustomerConditionerMapper;
|
@Autowired
|
private YwConditionerMapper ywConditionerMapper;
|
@Autowired
|
@Lazy
|
private YwCustomerRechargeBizService ywCustomerRechargeBizService;
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void syncByContractId(Integer contractId, LoginUserInfo user) {
|
if (contractId == null) {
|
return;
|
}
|
YwContract contract = ywContractMapper.selectById(contractId);
|
if (contract == null || Objects.equals(contract.getIsdeleted(), Constants.ONE) || contract.getRenterId() == null) {
|
return;
|
}
|
refreshCustomerDevices(contract.getRenterId(), user);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void syncByCustomerId(Integer customerId, LoginUserInfo user) {
|
refreshCustomerDevices(customerId, user);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void refreshCustomerDevices(Integer customerId, LoginUserInfo user) {
|
if (customerId == null) {
|
return;
|
}
|
LoginUserInfo opUser = user != null ? user : systemUser();
|
List<YwContract> contracts = ywContractMapper.selectList(new QueryWrapper<YwContract>().lambda()
|
.eq(YwContract::getRenterId, customerId)
|
.eq(YwContract::getIsdeleted, Constants.ZERO));
|
List<YwContract> activeContracts = contracts.stream().filter(this::isActiveContract).collect(Collectors.toList());
|
Set<Integer> activeContractIds = activeContracts.stream().map(YwContract::getId).collect(Collectors.toSet());
|
|
for (YwContract contract : contracts) {
|
if (!activeContractIds.contains(contract.getId())) {
|
unbindByContractId(contract.getId(), opUser);
|
}
|
}
|
|
Set<Integer> roomIds = new LinkedHashSet<>();
|
for (YwContract contract : activeContracts) {
|
roomIds.addAll(listContractRoomIds(contract.getId()));
|
}
|
if (roomIds.isEmpty()) {
|
clearContractElectricalBindings(customerId, opUser);
|
softDeleteAllConditionerRels(customerId, opUser);
|
return;
|
}
|
|
List<Integer> roomIdList = new ArrayList<>(roomIds);
|
for (YwContract contract : activeContracts) {
|
bindElectricals(contract, listContractRoomIds(contract.getId()), opUser);
|
}
|
bindConditionersMerged(customerId, roomIdList, opUser);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void unbindByContractId(Integer contractId, LoginUserInfo user) {
|
if (contractId == null) {
|
return;
|
}
|
Date now = new Date();
|
Integer editor = user != null ? user.getId() : null;
|
ywCustomerElectricalMapper.update(null, new UpdateWrapper<YwCustomerElectrical>().lambda()
|
.set(YwCustomerElectrical::getIsdeleted, Constants.ONE)
|
.set(YwCustomerElectrical::getEditDate, now)
|
.set(YwCustomerElectrical::getEditor, editor)
|
.eq(YwCustomerElectrical::getContractId, contractId)
|
.eq(YwCustomerElectrical::getBindSource, BIND_SOURCE_CONTRACT)
|
.eq(YwCustomerElectrical::getIsdeleted, Constants.ZERO));
|
}
|
|
@Override
|
public List<Integer> listActiveContractRoomIds(Integer customerId) {
|
if (customerId == null) {
|
return Collections.emptyList();
|
}
|
List<YwContract> active = listActiveContracts(customerId);
|
Set<Integer> roomIds = new LinkedHashSet<>();
|
for (YwContract contract : active) {
|
roomIds.addAll(listContractRoomIds(contract.getId()));
|
}
|
return new ArrayList<>(roomIds);
|
}
|
|
@Override
|
public List<Integer> listElectricalIdsByActiveContracts(Integer customerId) {
|
List<Integer> roomIds = listActiveContractRoomIds(customerId);
|
if (roomIds.isEmpty()) {
|
return Collections.emptyList();
|
}
|
return new ArrayList<>(resolveElectricalIdsFromRooms(roomIds));
|
}
|
|
@Override
|
public List<Integer> listConditionerIdsByActiveContracts(Integer customerId) {
|
List<Integer> roomIds = listActiveContractRoomIds(customerId);
|
if (roomIds.isEmpty()) {
|
return Collections.emptyList();
|
}
|
return new ArrayList<>(resolveConditionerIdsFromRooms(roomIds));
|
}
|
|
@Override
|
public Map<Integer, List<Integer>> batchListElectricalIdsByActiveContracts(List<Integer> customerIds) {
|
return batchResolveDeviceIds(customerIds, Constants.ZERO);
|
}
|
|
@Override
|
public Map<Integer, List<Integer>> batchListConditionerIdsByActiveContracts(List<Integer> customerIds) {
|
return batchResolveDeviceIds(customerIds, Constants.ONE);
|
}
|
|
private Map<Integer, List<Integer>> batchResolveDeviceIds(List<Integer> customerIds, int deviceType) {
|
if (CollectionUtils.isEmpty(customerIds)) {
|
return Collections.emptyMap();
|
}
|
Map<Integer, Set<Integer>> roomsByCustomer = batchActiveContractRoomIds(customerIds);
|
Set<Integer> allRoomIds = roomsByCustomer.values().stream()
|
.flatMap(Set::stream).collect(Collectors.toCollection(LinkedHashSet::new));
|
Map<Integer, Set<Integer>> devicesByRoom = mapDevicesByRoom(allRoomIds, deviceType);
|
|
Map<Integer, List<Integer>> result = new LinkedHashMap<>();
|
for (Integer customerId : customerIds) {
|
Set<Integer> roomIds = roomsByCustomer.getOrDefault(customerId, Collections.emptySet());
|
Set<Integer> deviceIds = new LinkedHashSet<>();
|
for (Integer roomId : roomIds) {
|
deviceIds.addAll(devicesByRoom.getOrDefault(roomId, Collections.emptySet()));
|
}
|
result.put(customerId, new ArrayList<>(deviceIds));
|
}
|
return result;
|
}
|
|
private Map<Integer, Set<Integer>> batchActiveContractRoomIds(List<Integer> customerIds) {
|
List<YwContract> contracts = ywContractMapper.selectList(new QueryWrapper<YwContract>().lambda()
|
.in(YwContract::getRenterId, customerIds)
|
.eq(YwContract::getIsdeleted, Constants.ZERO));
|
Map<Integer, List<YwContract>> activeByCustomer = contracts.stream()
|
.filter(this::isActiveContract)
|
.collect(Collectors.groupingBy(YwContract::getRenterId));
|
|
List<Integer> contractIds = activeByCustomer.values().stream()
|
.flatMap(List::stream).map(YwContract::getId).distinct().collect(Collectors.toList());
|
Map<Integer, List<Integer>> roomsByContract = loadContractRoomMap(contractIds);
|
|
Map<Integer, Set<Integer>> roomsByCustomer = new LinkedHashMap<>();
|
for (Integer customerId : customerIds) {
|
Set<Integer> roomIds = new LinkedHashSet<>();
|
for (YwContract contract : activeByCustomer.getOrDefault(customerId, Collections.emptyList())) {
|
roomIds.addAll(roomsByContract.getOrDefault(contract.getId(), Collections.emptyList()));
|
}
|
roomsByCustomer.put(customerId, roomIds);
|
}
|
return roomsByCustomer;
|
}
|
|
private Map<Integer, List<Integer>> loadContractRoomMap(List<Integer> contractIds) {
|
if (CollectionUtils.isEmpty(contractIds)) {
|
return Collections.emptyMap();
|
}
|
return ywContractRoomMapper.selectList(new QueryWrapper<YwContractRoom>().lambda()
|
.in(YwContractRoom::getContractId, contractIds)
|
.eq(YwContractRoom::getType, Constants.ZERO)
|
.eq(YwContractRoom::getIsdeleted, Constants.ZERO))
|
.stream()
|
.collect(Collectors.groupingBy(YwContractRoom::getContractId,
|
Collectors.mapping(YwContractRoom::getRoomId,
|
Collectors.collectingAndThen(Collectors.toList(),
|
list -> list.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList())))));
|
}
|
|
private Map<Integer, Set<Integer>> mapDevicesByRoom(Set<Integer> roomIds, int deviceType) {
|
if (CollectionUtils.isEmpty(roomIds)) {
|
return Collections.emptyMap();
|
}
|
List<Integer> roomIdList = new ArrayList<>(roomIds);
|
Map<Integer, Set<Integer>> result = new HashMap<>();
|
List<YwElectricalRoom> relRooms = ywElectricalRoomMapper.selectList(new QueryWrapper<YwElectricalRoom>().lambda()
|
.in(YwElectricalRoom::getRoomId, roomIdList)
|
.eq(YwElectricalRoom::getType, deviceType)
|
.eq(YwElectricalRoom::getIsdeleted, Constants.ZERO));
|
for (YwElectricalRoom rel : relRooms) {
|
if (rel.getRoomId() == null || rel.getObjId() == null) {
|
continue;
|
}
|
result.computeIfAbsent(rel.getRoomId(), k -> new LinkedHashSet<>()).add(rel.getObjId());
|
}
|
if (deviceType == Constants.ONE) {
|
List<YwConditioner> byRoom = ywConditionerMapper.selectList(new QueryWrapper<YwConditioner>().lambda()
|
.in(YwConditioner::getRoomId, roomIdList)
|
.eq(YwConditioner::getIsdeleted, Constants.ZERO));
|
for (YwConditioner conditioner : byRoom) {
|
if (conditioner.getRoomId() == null || conditioner.getId() == null) {
|
continue;
|
}
|
result.computeIfAbsent(conditioner.getRoomId(), k -> new LinkedHashSet<>()).add(conditioner.getId());
|
}
|
}
|
return result;
|
}
|
|
private List<YwContract> listActiveContracts(Integer customerId) {
|
return ywContractMapper.selectList(new QueryWrapper<YwContract>().lambda()
|
.eq(YwContract::getRenterId, customerId)
|
.eq(YwContract::getIsdeleted, Constants.ZERO))
|
.stream().filter(this::isActiveContract).collect(Collectors.toList());
|
}
|
|
private boolean isActiveContract(YwContract contract) {
|
if (contract == null || contract.getStartDate() == null || contract.getEndDate() == null) {
|
return false;
|
}
|
if (Objects.equals(contract.getStatus(), Constants.FOUR)) {
|
return false;
|
}
|
long now = System.currentTimeMillis();
|
return contract.getStartDate().getTime() <= now
|
&& Utils.Date.getEnd(contract.getEndDate()).getTime() >= now;
|
}
|
|
private List<Integer> listContractRoomIds(Integer contractId) {
|
return ywContractRoomMapper.selectList(new QueryWrapper<YwContractRoom>().lambda()
|
.eq(YwContractRoom::getContractId, contractId)
|
.eq(YwContractRoom::getType, Constants.ZERO)
|
.eq(YwContractRoom::getIsdeleted, Constants.ZERO))
|
.stream().map(YwContractRoom::getRoomId).filter(Objects::nonNull).distinct()
|
.collect(Collectors.toList());
|
}
|
|
private Set<Integer> resolveElectricalIdsFromRooms(List<Integer> roomIds) {
|
if (CollectionUtils.isEmpty(roomIds)) {
|
return Collections.emptySet();
|
}
|
return ywElectricalRoomMapper.selectList(new QueryWrapper<YwElectricalRoom>().lambda()
|
.in(YwElectricalRoom::getRoomId, roomIds)
|
.eq(YwElectricalRoom::getType, Constants.ZERO)
|
.eq(YwElectricalRoom::getIsdeleted, Constants.ZERO))
|
.stream().map(YwElectricalRoom::getObjId).filter(Objects::nonNull)
|
.collect(Collectors.toCollection(LinkedHashSet::new));
|
}
|
|
private Set<Integer> resolveConditionerIdsFromRooms(List<Integer> roomIds) {
|
if (CollectionUtils.isEmpty(roomIds)) {
|
return Collections.emptySet();
|
}
|
Set<Integer> conditionerIds = new LinkedHashSet<>();
|
List<YwElectricalRoom> acRooms = ywElectricalRoomMapper.selectList(new QueryWrapper<YwElectricalRoom>().lambda()
|
.in(YwElectricalRoom::getRoomId, roomIds)
|
.eq(YwElectricalRoom::getType, Constants.ONE)
|
.eq(YwElectricalRoom::getIsdeleted, Constants.ZERO));
|
acRooms.stream().map(YwElectricalRoom::getObjId).filter(Objects::nonNull).forEach(conditionerIds::add);
|
if (conditionerIds.isEmpty()) {
|
ywConditionerMapper.selectList(new QueryWrapper<YwConditioner>().lambda()
|
.in(YwConditioner::getRoomId, roomIds)
|
.eq(YwConditioner::getIsdeleted, Constants.ZERO))
|
.stream().map(YwConditioner::getId).filter(Objects::nonNull).forEach(conditionerIds::add);
|
}
|
return conditionerIds;
|
}
|
|
private void bindElectricals(YwContract contract, List<Integer> roomIds, LoginUserInfo user) {
|
Set<Integer> electricalIds = resolveElectricalIdsFromRooms(roomIds);
|
if (electricalIds.isEmpty()) {
|
return;
|
}
|
Set<Integer> boundOthers = listBoundElectricalIdsExcept(contract.getRenterId());
|
Date now = new Date();
|
for (Integer eid : electricalIds) {
|
if (boundOthers.contains(eid)) {
|
log.warn("skip electrical {} already bound to other customer", eid);
|
continue;
|
}
|
YwCustomerElectrical exist = ywCustomerElectricalMapper.selectOne(new QueryWrapper<YwCustomerElectrical>().lambda()
|
.eq(YwCustomerElectrical::getCustomerId, contract.getRenterId())
|
.eq(YwCustomerElectrical::getElectricalId, eid)
|
.eq(YwCustomerElectrical::getIsdeleted, Constants.ZERO)
|
.last("limit 1"));
|
if (exist != null) {
|
if (!Objects.equals(exist.getContractId(), contract.getId())
|
|| !Objects.equals(exist.getBindSource(), BIND_SOURCE_CONTRACT)) {
|
exist.setContractId(contract.getId());
|
exist.setBindSource(BIND_SOURCE_CONTRACT);
|
exist.setEditDate(now);
|
exist.setEditor(user != null ? user.getId() : null);
|
ywCustomerElectricalMapper.updateById(exist);
|
}
|
continue;
|
}
|
YwCustomerElectrical rel = new YwCustomerElectrical();
|
rel.setCreator(user != null ? user.getId() : null);
|
rel.setCreateDate(now);
|
rel.setEditor(user != null ? user.getId() : null);
|
rel.setEditDate(now);
|
rel.setIsdeleted(Constants.ZERO);
|
rel.setCustomerId(contract.getRenterId());
|
rel.setElectricalId(eid);
|
rel.setBindSource(BIND_SOURCE_CONTRACT);
|
rel.setContractId(contract.getId());
|
ywCustomerElectricalMapper.insert(rel);
|
}
|
}
|
|
private void bindConditionersMerged(Integer customerId, List<Integer> roomIds, LoginUserInfo user) {
|
Set<Integer> conditionerIds = resolveConditionerIdsFromRooms(roomIds);
|
if (conditionerIds.isEmpty()) {
|
softDeleteAllConditionerRels(customerId, user);
|
return;
|
}
|
YwCustomerGsConfigDTO dto = new YwCustomerGsConfigDTO();
|
dto.setCustomerId(customerId);
|
dto.setIsPwr(Constants.ONE);
|
dto.setIsRestStop(Constants.ZERO);
|
dto.setGsBz("合同自动关联");
|
dto.setStopMoney(BigDecimal.ZERO);
|
List<YwCustomerGsConfigDTO.ConditionerItem> items = new ArrayList<>();
|
for (Integer cid : conditionerIds) {
|
YwCustomerGsConfigDTO.ConditionerItem item = new YwCustomerGsConfigDTO.ConditionerItem();
|
item.setConditionerId(cid);
|
item.setDevRatio(100);
|
items.add(item);
|
}
|
dto.setConditioners(items);
|
try {
|
ywCustomerRechargeBizService.saveCustomerGsConfig(dto, user);
|
} catch (BusinessException e) {
|
log.warn("auto bind conditioner GS failed customerId={}: {}", customerId, e.getMessage());
|
}
|
}
|
|
private void clearContractElectricalBindings(Integer customerId, LoginUserInfo user) {
|
Date now = new Date();
|
ywCustomerElectricalMapper.update(null, new UpdateWrapper<YwCustomerElectrical>().lambda()
|
.set(YwCustomerElectrical::getIsdeleted, Constants.ONE)
|
.set(YwCustomerElectrical::getEditDate, now)
|
.set(YwCustomerElectrical::getEditor, user != null ? user.getId() : null)
|
.eq(YwCustomerElectrical::getCustomerId, customerId)
|
.eq(YwCustomerElectrical::getBindSource, BIND_SOURCE_CONTRACT)
|
.eq(YwCustomerElectrical::getIsdeleted, Constants.ZERO));
|
}
|
|
private void softDeleteAllConditionerRels(Integer customerId, LoginUserInfo user) {
|
Date now = new Date();
|
ywCustomerConditionerMapper.update(null, new UpdateWrapper<YwCustomerConditioner>().lambda()
|
.set(YwCustomerConditioner::getIsdeleted, Constants.ONE)
|
.set(YwCustomerConditioner::getEditDate, now)
|
.set(YwCustomerConditioner::getEditor, user != null ? user.getId() : null)
|
.eq(YwCustomerConditioner::getCustomerId, customerId)
|
.eq(YwCustomerConditioner::getIsdeleted, Constants.ZERO));
|
}
|
|
private Set<Integer> listBoundElectricalIdsExcept(Integer customerId) {
|
List<YwCustomerElectrical> list = ywCustomerElectricalMapper.selectList(new QueryWrapper<YwCustomerElectrical>().lambda()
|
.eq(YwCustomerElectrical::getIsdeleted, Constants.ZERO)
|
.ne(customerId != null, YwCustomerElectrical::getCustomerId, customerId));
|
return list.stream().map(YwCustomerElectrical::getElectricalId).collect(Collectors.toSet());
|
}
|
|
private LoginUserInfo systemUser() {
|
LoginUserInfo u = new LoginUserInfo();
|
u.setId(1);
|
u.setRealname("system");
|
return u;
|
}
|
}
|