Commit a3266dd6 by HlQ

[chg] 项目维保状态逻辑修改

[add]
1.设备返修和备件申请支持发货日期查询
2.项目列表添加参数
1 parent 819a2bea
......@@ -121,4 +121,9 @@ public class RepairRecDTO extends BaseDTO {
private Date createTimeStart;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTimeEnd;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date shipDateStart;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date shipDateEnd;
}
\ No newline at end of file
......@@ -117,4 +117,9 @@ public class SparePartDTO extends BaseDTO {
private Date createTimeStart;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTimeEnd;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date shipDateStart;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date shipDateEnd;
}
\ No newline at end of file
......@@ -59,6 +59,17 @@ public class StoreDTO extends BaseDTO {
private String stuckPoint;
/** 标签id */
private Long tagId;
/** 项目负责人 or 项目经理 */
private Long mainUser;
/** 主要产品 */
private Integer mainProduct;
/** 点位数量 */
private Integer pointNum;
/** 计划完成日期 */
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date planFinishDate;
/** 项目规模 */
private Integer projectSize;
private Long sourceId;
private Long targetId;
......
......@@ -71,7 +71,7 @@ public class Store {
/** 任务详情 */
private String taskDetail;
/** 预计完成日期 */
/** 实际完成日期 */
private Date finishDate;
/** 完成百分比 */
......@@ -80,4 +80,16 @@ public class Store {
/** 当前卡点 */
private String stuckPoint;
/** 主要产品 */
private Integer mainProduct;
/** 点位数量 */
private Integer pointNum;
/** 计划完成日期 */
private Date planFinishDate;
/** 项目规模 */
private Integer projectSize;
}
package vion.service.impl;
import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.io.file.FileNameUtil;
import org.dromara.hutool.core.io.file.FileUtil;
......@@ -93,6 +94,7 @@ public class RepairRecServiceImpl extends MPJBaseServiceImpl<RepairRecMapper, Re
.leftJoin(Store.class, Store::getId, RepairRec::getStoreId)
.leftJoin(RRepairDevice.class, on -> on.eq(RRepairDevice::getRId, RepairRec::getId).eq(RRepairDevice::getRType, 2))
.between(RepairRec::getCreateTime, dto.getCreateTimeStart(), dto.getCreateTimeEnd())
.between(ArrayUtil.isAllNotNull(dto.getShipDateStart(), dto.getShipDateEnd()), SparePart::getShipDate, dto.getShipDateStart(), dto.getShipDateEnd())
.orderByDesc(RepairRec::getCreateTime);
return this.selectJoinList(RepairRecVO.class, wrapper);
}
......
package vion.service.impl;
import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.io.file.FileNameUtil;
import org.dromara.hutool.core.io.file.FileUtil;
......@@ -91,6 +92,7 @@ public class SparePartServiceImpl extends MPJBaseServiceImpl<SparePartMapper, Sp
.leftJoin(Contract.class, Contract::getId, SparePart::getContractId)
.leftJoin(RRepairDevice.class, on -> on.eq(RRepairDevice::getRId, SparePart::getId).eq(RRepairDevice::getRType, 1))
.between(SparePart::getCreateTime, dto.getCreateTimeStart(), dto.getCreateTimeEnd())
.between(ArrayUtil.isAllNotNull(dto.getShipDateStart(), dto.getShipDateEnd()), SparePart::getShipDate, dto.getShipDateStart(), dto.getShipDateEnd())
.orderByDesc(SparePart::getCreateTime);
return this.selectJoinList(SparePartVO.class, wrapper);
}
......
package vion.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import io.github.linpeilie.Converter;
import lombok.RequiredArgsConstructor;
import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.io.file.FileNameUtil;
import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.lang.Opt;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import io.github.linpeilie.Converter;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
......@@ -54,6 +54,7 @@ public class StoreServiceImpl extends MPJBaseServiceImpl<StoreMapper, Store> imp
private final IInspectService inspectService;
private final ITagService tagService;
private final IRStoreTagService storeTagService;
private final IRStoreUserService storeUserService;
private final Converter converter;
// 引入 taskService 会循环依赖
private final TaskMapper taskMapper;
......@@ -63,40 +64,46 @@ public class StoreServiceImpl extends MPJBaseServiceImpl<StoreMapper, Store> imp
@Override
public Page<StoreVO> getStoreList(StoreDTO data) {
List<Long> storeIdListByTagId = new ArrayList<>();
if (ObjUtil.isNotNull(data.getTagId())) {
List<RStoreTag> storeTagList = storeTagService.lambdaQuery().eq(RStoreTag::getTagId, data.getTagId()).list();
storeIdListByTagId = storeTagList.stream().map(RStoreTag::getStoreId).collect(Collectors.toList());
if (CollUtil.isEmpty(storeIdListByTagId)) {
storeIdListByTagId.add(-1L);
}
}
var storeIdListByTagId = Optional.ofNullable(data.getTagId())
.map(tagId -> storeTagService.lambdaQuery().eq(RStoreTag::getTagId, tagId).list())
.map(storeTagList -> storeTagList.stream().map(RStoreTag::getStoreId).collect(Collectors.toList()))
.filter(CollUtil::isNotEmpty)
.orElse(List.of(-1L));
Store store = converter.convert(data, Store.class);
Page<Store> storeList = this.lambdaQuery(store)
.in(CollUtil.isNotEmpty(storeIdListByTagId), Store::getId, storeIdListByTagId)
var storeIdListByMainUser = Optional.ofNullable(data.getMainUser())
.map(mainUser -> storeUserService.lambdaQuery().eq(RStoreUser::getUserId, mainUser).eq(RStoreUser::getIsMain, 1).list())
.map(storeUserList -> storeUserList.stream().map(RStoreUser::getStoreId).collect(Collectors.toList()))
.filter(CollUtil::isNotEmpty)
.orElse(List.of(-1L));
var store = converter.convert(data, Store.class);
var storeList = this.lambdaQuery(store)
.in(ObjUtil.notEquals(storeIdListByTagId.get(0), -1L), Store::getId, storeIdListByTagId)
.in(ObjUtil.notEquals(storeIdListByMainUser.get(0), -1L), Store::getId, storeIdListByMainUser)
.orderByDesc(Store::getIsImportant, Store::getCreateTime)
.page(Page.of(data.getPageNum(), data.getPageSize()));
// todo 缓存
List<Account> accountList = accountService.list();
List<FileInfo> fileInfoList = fileService.lambdaQuery().eq(FileInfo::getSourceType, 1).list();
Map<Long, Long> store2CntMap = fileInfoList.stream().collect(Collectors.groupingBy(FileInfo::getStoreId, Collectors.counting()));
var store2CntMap = fileInfoList.stream().collect(Collectors.groupingBy(FileInfo::getStoreId, Collectors.counting()));
List<Long> storeIdList = Opt.ofEmptyAble(storeList.getRecords())
var storeIdList = Opt.ofEmptyAble(storeList.getRecords())
.map(recs -> recs.stream().map(Store::getId).collect(Collectors.toList()))
.orElse(ListUtil.empty());
// storeId -> 项目绑定的合同的 list
Map<Long, List<RContractStore>> storeIdMap = Opt.ofEmptyAble(storeIdList)
var storeIdMap = Opt.ofEmptyAble(storeIdList)
.map(l -> contractStoreService.lambdaQuery().in(RContractStore::getStoreId, l).list())
.map(contractStoreList -> contractStoreList.stream().collect(Collectors.groupingBy(RContractStore::getStoreId)))
.orElse(MapUtil.empty());
// 项目绑定的合同的id
List<Long> contractIdList = Opt.ofEmptyAble(storeIdMap.values())
.map(l -> l.stream().flatMap(List::stream).collect(Collectors.toList()))
.filter(CollUtil::isNotEmpty)
.map(contractStoreList -> contractStoreList.stream().map(RContractStore::getContractId).collect(Collectors.toList())).
orElse(ListUtil.empty());
var contractIdList = Opt.ofEmptyAble(storeIdMap.values())
.map(values -> values.stream()
.flatMap(List::stream)
.map(RContractStore::getContractId)
.collect(Collectors.toList()))
.orElse(Collections.emptyList());
// contractId -> contract
Map<Long, Contract> id2ContractMap = Opt.ofEmptyAble(contractIdList)
var id2ContractMap = Opt.ofEmptyAble(contractIdList)
.map(l -> contractService.lambdaQuery()
.select(Contract::getId, Contract::getName, Contract::getContractNo, Contract::getType, Contract::getSignDate, Contract::getWarrantyPeriod, Contract::getFinalDate, Contract::getStatus, Contract::getSaleName, Contract::getCustomerName, Contract::getMaintainSdate, Contract::getMaintainEdate)
.in(Contract::getId, l).list())
......@@ -104,7 +111,7 @@ public class StoreServiceImpl extends MPJBaseServiceImpl<StoreMapper, Store> imp
.orElse(MapUtil.empty());
// contractId -> 合同付款约定
Map<Long, List<ContractPayment>> contractId2CpMap = Opt.ofEmptyAble(contractIdList)
var contractId2CpMap = Opt.ofEmptyAble(contractIdList)
.map(l -> contractPaymentService.lambdaQuery().in(ContractPayment::getContractId, l).in(ContractPayment::getPaymentType, 3, 4).isNotNull(ContractPayment::getNodeDate).list())
.map(contractPaymentList -> contractPaymentList.stream().collect(Collectors.groupingBy(ContractPayment::getContractId, Collectors.collectingAndThen(Collectors.toList(), v -> {
v.sort(Comparator.comparing(ContractPayment::getPaymentType).reversed());
......@@ -112,20 +119,21 @@ public class StoreServiceImpl extends MPJBaseServiceImpl<StoreMapper, Store> imp
}))))
.orElse(MapUtil.empty());
Map<Long, List<Long>> store2TaskIdMap = Opt.ofEmptyAble(storeIdList)
// storeId -> taskIdList
var store2TaskIdMap = Opt.ofEmptyAble(storeIdList)
.map(l -> taskMapper.selectList(Wrappers.lambdaQuery(Task.class).in(Task::getStoreId, l)))
.map(taskList -> taskList.stream().collect(Collectors.groupingBy(Task::getStoreId, Collectors.mapping(Task::getId, Collectors.toList()))))
.orElse(MapUtil.empty());
List<Long> taskIds = store2TaskIdMap.values().stream()
var taskIds = store2TaskIdMap.values().stream()
.flatMap(List::stream)
.collect(Collectors.toList());
Map<Long, List<ServiceOrder>> taskServiceOrderMap = Opt.ofEmptyAble(taskIds)
var taskServiceOrderMap = Opt.ofEmptyAble(taskIds)
.map(t -> Db.list(Wrappers.lambdaQuery(ServiceOrder.class).in(ServiceOrder::getTaskId, taskIds)))
.map(serviceOrderList -> serviceOrderList.stream().collect(Collectors.groupingBy(ServiceOrder::getTaskId)))
.orElse(MapUtil.empty());
// storeId -> tagList
Map<Long, List<TagVO>> storeId2TagMap = Opt.ofEmptyAble(storeIdList)
var storeId2TagMap = Opt.ofEmptyAble(storeIdList)
.map(l -> {
MPJLambdaWrapper<Tag> wrapper = new MPJLambdaWrapper<Tag>()
.select(Tag::getId, Tag::getName, Tag::getRemark)
......@@ -138,41 +146,49 @@ public class StoreServiceImpl extends MPJBaseServiceImpl<StoreMapper, Store> imp
.map(tagVOS -> tagVOS.stream().collect(Collectors.groupingBy(TagVO::getStoreId)))
.orElse(MapUtil.empty());
// storeId -> userId(项目主要负责人 or 项目经理)
var storeId2UserIdMap = Opt.ofEmptyAble(storeIdList)
.map(l -> storeUserService.lambdaQuery().in(RStoreUser::getStoreId, l).eq(RStoreUser::getIsMain, 1).list())
.map(suList -> suList.stream().collect(Collectors.toMap(RStoreUser::getStoreId, RStoreUser::getUserId)))
.orElse(MapUtil.empty());
List<StoreVO> storeVOList = new ArrayList<>();
storeList.getRecords().forEach(item -> {
StoreVO storeVO = converter.convert(item, StoreVO.class);
var storeVO = converter.convert(item, StoreVO.class);
storeVO.setAccountName(accountList.stream().filter(v -> v.getId().equals(item.getAccountId())).map(Account::getName).findFirst().orElse("--"));
storeVO.setFileNum(store2CntMap.getOrDefault(item.getId(), 0L));
Long storeId = item.getId();
// 关联合同
List<RContractStore> contractStores = storeIdMap.get(storeId);
var contractStores = storeIdMap.get(storeId);
storeVO.setContractCount(Opt.ofEmptyAble(contractStores).map(List::size).orElse(0));
storeVO.setContractVOList(id2ContractMap.values().stream()
.filter(v -> CollUtil.isNotEmpty(contractStores) && contractStores.stream().map(RContractStore::getContractId).collect(Collectors.toList()).contains(v.getId()))
.filter(v -> CollUtil.isNotEmpty(contractStores) && contractStores.stream().map(RContractStore::getContractId).toList().contains(v.getId()))
.map(v -> converter.convert(v, ContractVO.class))
.collect(Collectors.toList()));
Contract masterContract = id2ContractMap.getOrDefault(item.getMasterContract(), null);
var masterContract = id2ContractMap.getOrDefault(item.getMasterContract(), null);
// 关联合同验收时间
Opt.ofNullable(masterContract)
.map(c -> contractId2CpMap.getOrDefault(c.getId(), ListUtil.empty()))
.filter(CollUtil::isNotEmpty)
.map(l -> l.get(0).getNodeDate())
.ifPresent(nodeDate -> masterContract.setFinalDate(nodeDate));
.ifPresent(masterContract::setFinalDate);
storeVO.setMainContract(Opt.ofNullable(masterContract).map(c -> converter.convert(c, ContractVO.class)).orElse(null));
storeVO.setTaskCount(store2TaskIdMap.getOrDefault(storeId, ListUtil.empty()).size());
// 补充服务单
if (store2TaskIdMap.containsKey(item.getId())) {
List<ServiceOrder> serviceOrders = store2TaskIdMap.get(item.getId())
.stream().flatMap(taskId -> taskServiceOrderMap.getOrDefault(taskId, ListUtil.empty()).stream())
.collect(Collectors.toList());
storeVO.setServiceOrderCount(serviceOrders.size());
var cnt = store2TaskIdMap.get(item.getId())
.stream().mapToLong(taskId -> taskServiceOrderMap.getOrDefault(taskId, ListUtil.empty()).size()).sum();
storeVO.setServiceOrderCount((int) cnt);
}
// 关联标签
storeVO.setTagList(storeId2TagMap.getOrDefault(storeId, ListUtil.empty()));
// 关联项目负责人 or 项目经理
storeVO.setMainUser(storeId2UserIdMap.getOrDefault(storeId, null));
storeVOList.add(storeVO);
});
return Page.<StoreVO>of(data.getPageNum(), data.getPageSize(), storeList.getTotal()).setRecords(storeVOList);
......@@ -223,7 +239,7 @@ public class StoreServiceImpl extends MPJBaseServiceImpl<StoreMapper, Store> imp
.map(l -> l.stream().collect(Collectors.groupingBy(RContractStore::getStoreId, Collectors.mapping(RContractStore::getContractId, Collectors.toList()))))
.orElse(MapUtil.empty());
List<Contract> contractList = contractService.listByIds(storeId2ContractIdMap.values().stream().flatMap(List::stream).collect(Collectors.toList()));
// 根据 storeList、storeId2ContractIdMap、contractList,得到一个storeId 为 key,List<Contract> 为 value 的 map
// storeId 为 key,List<Contract> 为 value 的 map
Map<Long, List<Contract>> storeId2ContractListMap = storeList.stream()
.collect(Collectors.toMap(Store::getId, store ->
storeId2ContractIdMap.getOrDefault(store.getId(), ListUtil.empty())
......@@ -232,6 +248,13 @@ public class StoreServiceImpl extends MPJBaseServiceImpl<StoreMapper, Store> imp
.filter(Objects::nonNull)
.collect(Collectors.toList())));
var contractId2CpMap = Opt.ofEmptyAble(contractPaymentService.lambdaQuery().in(ContractPayment::getPaymentType, 3, 4).isNotNull(ContractPayment::getNodeDate).list())
.map(contractPaymentList -> contractPaymentList.stream().collect(Collectors.groupingBy(ContractPayment::getContractId, Collectors.collectingAndThen(Collectors.toList(), v -> {
v.sort(Comparator.comparing(ContractPayment::getPaymentType).reversed());
return v;
}))))
.orElse(MapUtil.empty());
List<Store> updStoreList = new ArrayList<>();
for (Store s : storeList) {
s.setMaintainStatus("--");
......@@ -240,13 +263,23 @@ public class StoreServiceImpl extends MPJBaseServiceImpl<StoreMapper, Store> imp
// 1.项目关联的主合同在维保期内,那么这个项目就是在保
Contract masterContract = contracts.stream().filter(contract -> ObjUtil.equals(contract.getId(), s.getMasterContract())).findFirst().orElse(null);
if (ObjUtil.isNotNull(masterContract)) {
Date finalDate = masterContract.getFinalDate();
Integer warrantyPeriod = masterContract.getWarrantyPeriod();
Opt.ofNullable(contractId2CpMap.getOrDefault(masterContract.getId(), ListUtil.empty()))
.filter(CollUtil::isNotEmpty)
.map(l -> l.get(0).getNodeDate())
.ifPresent(masterContract::setFinalDate);
Date finalDate = masterContract.getFinalDate();
if (ArrayUtil.isAllNotNull(finalDate, warrantyPeriod)) {
Date finalDateEnd = DateUtil.offsetMonth(finalDate, warrantyPeriod);
boolean isIn = DateUtil.isIn(new Date(), finalDate, finalDateEnd);
if (isIn) {
s.setMaintainStatus("在保");
Store updStore = new Store();
updStore.setId(s.getId());
updStore.setMaintainStatus(s.getMaintainStatus());
updStoreList.add(updStore);
continue;
} else {
s.setMaintainStatus("脱保");
......@@ -258,13 +291,9 @@ public class StoreServiceImpl extends MPJBaseServiceImpl<StoreMapper, Store> imp
Set<Boolean> maintainStatusSet = new HashSet<>();
contracts.stream()
.filter(contract -> ObjUtil.equals(contract.getType(), 1))
.forEach(c -> {
Date maintainEdate = c.getMaintainEdate();
if (ObjUtil.isNotNull(maintainEdate)) {
// 维保结束时间大于等于当前时间,返回 true
maintainStatusSet.add(DateUtil.compare(maintainEdate, new Date()) >= 0);
}
});
.map(Contract::getMaintainEdate)
.filter(Objects::nonNull)
.forEach(maintainEdate -> maintainStatusSet.add(DateUtil.compare(maintainEdate, new Date()) >= 0));
s.setMaintainStatus(CollUtil.isEmpty(maintainStatusSet) ? s.getMaintainStatus() : maintainStatusSet.contains(true) ? "在保" : "脱保");
}
Store updStore = new Store();
......
......@@ -78,7 +78,7 @@ public class StoreVO {
*/
private String taskDetail;
/**
* 预计完成日期
* 实际完成日期
*/
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date finishDate;
......@@ -90,6 +90,26 @@ public class StoreVO {
* 当前卡点
*/
private String stuckPoint;
/**
* 主要产品
*/
private Integer mainProduct;
/**
* 点位数量
*/
private Integer pointNum;
/**
* 计划完成日期
*/
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date planFinishDate;
/**
* 项目规模
*/
private Integer projectSize;
private List<String> userNameList;
......@@ -118,4 +138,9 @@ public class StoreVO {
* 标签
*/
private List<TagVO> tagList;
/**
* 项目负责人 or 项目经理
*/
private Long mainUser;
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!