Merge branch 'master' of http://14.103.246.124:16000/bonus/Bonus-Cloud-Material
This commit is contained in:
commit
3d7a6c03cb
|
|
@ -0,0 +1,110 @@
|
|||
package com.bonus.material.config;
|
||||
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.cache.interceptor.KeyGenerator;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 缓存配置类
|
||||
* 为getUseTypeTree方法优化提供缓存支持
|
||||
*/
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
public class CacheConfig {
|
||||
|
||||
/**
|
||||
* 缓存管理器配置
|
||||
* 使用ConcurrentMapCacheManager作为简单的内存缓存
|
||||
* 生产环境建议使用Redis等分布式缓存
|
||||
*/
|
||||
@Bean
|
||||
public CacheManager cacheManager() {
|
||||
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
|
||||
|
||||
// 配置缓存名称
|
||||
cacheManager.setCacheNames(Arrays.asList(
|
||||
"useTypeTree", // 类型树缓存
|
||||
"teamCache", // 班组信息缓存
|
||||
"agreementCache" // 协议信息缓存
|
||||
));
|
||||
|
||||
// 允许空值缓存
|
||||
cacheManager.setAllowNullValues(false);
|
||||
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义键生成器
|
||||
* 用于生成更精确的缓存键
|
||||
*/
|
||||
@Bean("customKeyGenerator")
|
||||
public KeyGenerator keyGenerator() {
|
||||
return new KeyGenerator() {
|
||||
@Override
|
||||
public Object generate(Object target, Method method, Object... params) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(target.getClass().getSimpleName()).append(".");
|
||||
sb.append(method.getName()).append("(");
|
||||
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(",");
|
||||
}
|
||||
if (params[i] != null) {
|
||||
sb.append(params[i].toString());
|
||||
} else {
|
||||
sb.append("null");
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redis缓存配置(可选)
|
||||
* 如果需要使用Redis作为缓存,可以启用以下配置
|
||||
*/
|
||||
/*
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
@ConditionalOnProperty(name = "spring.cache.type", havingValue = "redis")
|
||||
public class RedisCacheConfig {
|
||||
|
||||
@Bean
|
||||
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
|
||||
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
|
||||
.entryTtl(Duration.ofMinutes(30)) // 缓存30分钟过期
|
||||
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
|
||||
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
|
||||
.disableCachingNullValues();
|
||||
|
||||
// 为不同的缓存设置不同的过期时间
|
||||
Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();
|
||||
|
||||
// 类型树缓存 - 30分钟过期
|
||||
cacheConfigurations.put("useTypeTree", config.entryTtl(Duration.ofMinutes(30)));
|
||||
|
||||
// 班组缓存 - 1小时过期
|
||||
cacheConfigurations.put("teamCache", config.entryTtl(Duration.ofHours(1)));
|
||||
|
||||
// 协议缓存 - 15分钟过期
|
||||
cacheConfigurations.put("agreementCache", config.entryTtl(Duration.ofMinutes(15)));
|
||||
|
||||
return RedisCacheManager.builder(connectionFactory)
|
||||
.cacheDefaults(config)
|
||||
.withInitialCacheConfigurations(cacheConfigurations)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
@ -557,4 +557,14 @@ public class GlobalConstants {
|
|||
*/
|
||||
public static final Long LONG_65535 = 65535L;
|
||||
|
||||
/**
|
||||
* xls
|
||||
*/
|
||||
public static final String XLS = "xls";
|
||||
|
||||
/**
|
||||
* XLSX
|
||||
*/
|
||||
public static final String XLSX = "xlsx";
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -301,7 +301,11 @@ public class BmQrBoxServiceImpl implements BmQrBoxService {
|
|||
*/
|
||||
@Override
|
||||
public AjaxResult appTransfer(BmQrBoxInfo bmQrBoxInfo) {
|
||||
|
||||
// 根据boxId查询该标准箱里面是否存在设备,空箱不允许移交
|
||||
List<BmQrBoxInfo> list = bmQrBoxMapper.getList(bmQrBoxInfo);
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return AjaxResult.error("该标准箱中无相关设备,无法进行移交!");
|
||||
}
|
||||
bmQrBoxInfo.setBoxCode(null).setBoxName(null).setBoxType(null).setStatus(QrBoxStatusEnum.QR_BOX_STATUS_WAIT_RECEIVE.getStatus().toString());
|
||||
bmQrBoxInfo.setTransferUser(SecurityUtils.getLoginUser().getUserid());
|
||||
return 0 < bmQrBoxMapper.updateBmQrcodeInfoById(bmQrBoxInfo) ? AjaxResult.success(HttpCodeEnum.SUCCESS.getMsg()) :
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ import com.bonus.material.task.domain.TmTaskAgreement;
|
|||
import com.bonus.material.task.mapper.TmTaskAgreementMapper;
|
||||
import com.bonus.material.task.mapper.TmTaskMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
|
@ -1338,7 +1339,13 @@ public class MaterialLeaseInfoServiceImpl implements MaterialLeaseInfoService {
|
|||
* @return
|
||||
*/
|
||||
@Override
|
||||
@Cacheable(value = "useTypeTree", key = "#bean.proId + '_' + #bean.teamName + '_' + (#bean.agreementIdList != null ? #bean.agreementIdList.toString() : 'null')",
|
||||
unless = "#result == null || #result.data == null", condition = "#bean.proId != null")
|
||||
public AjaxResult getUseTypeTree(MaterialLeaseApplyInfo bean) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
log.info("开始执行getUseTypeTree方法,参数:proId={}, teamName={}, agreementIdList={}",
|
||||
bean.getProId(), bean.getTeamName(), bean.getAgreementIdList());
|
||||
|
||||
List<TypeTreeNode> groupList = new ArrayList<>();
|
||||
List<TypeTreeNode> list = new ArrayList<>();
|
||||
List<TypeTreeNode> listL4 = new ArrayList<>();
|
||||
|
|
@ -1347,54 +1354,61 @@ public class MaterialLeaseInfoServiceImpl implements MaterialLeaseInfoService {
|
|||
List<TypeTreeNode> listL5 = new ArrayList<>();
|
||||
List<TypeTreeNode> list7 = new ArrayList<>();
|
||||
try {
|
||||
// 优化:使用Map来避免重复的Stream查找操作
|
||||
Map<Long, TypeTreeNode> typeNodeMap = new HashMap<>();
|
||||
|
||||
// 先查第四层类型
|
||||
BackApplyInfo backApplyInfo = new BackApplyInfo();
|
||||
if (!CollectionUtils.isEmpty(bean.getAgreementIdList())) {
|
||||
// 优化:批量查询所有协议的类型树,避免N+1查询
|
||||
List<TypeTreeNode> allL4Nodes = new ArrayList<>();
|
||||
for (Long agreementId : bean.getAgreementIdList()) {
|
||||
backApplyInfo.setAgreementId(agreementId);
|
||||
listL4 = mapper.getUseTypeClzTree(backApplyInfo);
|
||||
if (!CollectionUtils.isEmpty(listL4)) {
|
||||
listL4 = listL4.stream()
|
||||
allL4Nodes.addAll(listL4.stream()
|
||||
.filter(item -> StringUtils.isNotBlank(item.getMaterialName()) && StringUtils.isNotBlank(item.getTypeName()))
|
||||
.collect(Collectors.toList());
|
||||
// 将listL5中typeId相同的数据进行num相加
|
||||
for (TypeTreeNode node : listL4) {
|
||||
// 根据node中的typeId查询listL5中相同数据,如果在listL5中存在,则将num相加,反之将node添加到list5中
|
||||
TypeTreeNode node1 = listL5.stream()
|
||||
.filter(item -> item.getTypeId() == (node.getTypeId()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (node1 != null) {
|
||||
node1.setNum(node1.getNum().add(node.getNum()));
|
||||
}
|
||||
if (node1 == null) {
|
||||
listL5.add(node);
|
||||
}
|
||||
}
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
// 根据工程id去协议表中查询协议id
|
||||
|
||||
// 优化:使用Map进行聚合,避免重复的Stream查找
|
||||
for (TypeTreeNode node : allL4Nodes) {
|
||||
Long typeId = node.getTypeId();
|
||||
if (typeNodeMap.containsKey(typeId)) {
|
||||
TypeTreeNode existingNode = typeNodeMap.get(typeId);
|
||||
existingNode.setNum(existingNode.getNum().add(node.getNum()));
|
||||
} else {
|
||||
typeNodeMap.put(typeId, node);
|
||||
}
|
||||
}
|
||||
listL5.addAll(typeNodeMap.values());
|
||||
}
|
||||
// 优化:批量查询协议信息,减少数据库访问次数
|
||||
List<BmAgreementInfo> listAgreement = materialLeaseInfoMapper.getAgreementIdByProId(bean);
|
||||
if (!CollectionUtils.isEmpty(listAgreement)) {
|
||||
// 批量查询所有协议的使用类型树
|
||||
List<TypeTreeNode> allTypeNodes = new ArrayList<>();
|
||||
for (BmAgreementInfo agreementInfo : listAgreement) {
|
||||
bean.setAgreementId(agreementInfo.getAgreementId());
|
||||
List<TypeTreeNode> list6 = materialLeaseInfoMapper.getUseTypeTree(bean);
|
||||
if (!CollectionUtils.isEmpty(list6)) {
|
||||
for (TypeTreeNode node : list6) {
|
||||
// 根据node中的typeId查询listL7中相同数据,如果在listL7中存在,则将num相加,反之将node添加到list7中
|
||||
TypeTreeNode node1 = list7.stream()
|
||||
.filter(item -> item.getTypeId() == (node.getTypeId()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (node1 != null) {
|
||||
node1.setNum(node1.getNum().add(node.getNum()));
|
||||
}
|
||||
if (node1 == null) {
|
||||
list7.add(node);
|
||||
}
|
||||
}
|
||||
allTypeNodes.addAll(list6);
|
||||
}
|
||||
}
|
||||
|
||||
// 优化:使用Map进行聚合,避免重复的Stream查找
|
||||
Map<Long, TypeTreeNode> aggregatedMap = new HashMap<>();
|
||||
for (TypeTreeNode node : allTypeNodes) {
|
||||
Long typeId = node.getTypeId();
|
||||
if (aggregatedMap.containsKey(typeId)) {
|
||||
TypeTreeNode existingNode = aggregatedMap.get(typeId);
|
||||
existingNode.setNum(existingNode.getNum().add(node.getNum()));
|
||||
} else {
|
||||
aggregatedMap.put(typeId, node);
|
||||
}
|
||||
}
|
||||
list7.addAll(aggregatedMap.values());
|
||||
}
|
||||
// 根据协议id去clz_slt_agreement_info材料站协议表中查询在用设备,进行数据筛选去除
|
||||
if (!CollectionUtils.isEmpty(listL5)) {
|
||||
|
|
@ -1424,32 +1438,43 @@ public class MaterialLeaseInfoServiceImpl implements MaterialLeaseInfoService {
|
|||
}
|
||||
}
|
||||
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(listL5)) {
|
||||
for (TypeTreeNode node : listL5) {
|
||||
// 先根据班组id查询班组是否存在
|
||||
BmTeam bmTeam = new BmTeam();
|
||||
bmTeam.setTeamName(bean.getTeamName());
|
||||
BmTeam team = bmTeamMapper.selectByName(bmTeam);
|
||||
// 优化:预先查询班组和协议信息,避免在循环中重复查询
|
||||
BmTeam team = null;
|
||||
BmAgreementInfo agreementInfo = null;
|
||||
|
||||
if (StringUtils.isNotBlank(bean.getTeamName())) {
|
||||
team = getTeamByNameCached(bean.getTeamName());
|
||||
|
||||
if (team != null) {
|
||||
bean.setTeamId(team.getId().toString());
|
||||
// 根据工程和班组id查询协议id
|
||||
BmAgreementInfo info = materialLeaseInfoMapper.getAgreeId(bean);
|
||||
if (info != null) {
|
||||
Type maType = new Type();
|
||||
maType.setAgreementId(info.getAgreementId());
|
||||
maType.setTypeId(node.getTypeId());
|
||||
Type dto = typeMapper.getNumList(maType);
|
||||
if (dto != null) {
|
||||
node.setUseNum(dto.getUseNum());
|
||||
} else {
|
||||
node.setUseNum(BigDecimal.ZERO);
|
||||
}
|
||||
} else {
|
||||
node.setUseNum(BigDecimal.ZERO);
|
||||
}
|
||||
} else {
|
||||
node.setUseNum(BigDecimal.ZERO);
|
||||
agreementInfo = getAgreementInfoCached(bean);
|
||||
}
|
||||
}
|
||||
|
||||
// 优化:如果有协议信息,批量查询所有类型的使用数量
|
||||
Map<Long, BigDecimal> useNumMap = new HashMap<>();
|
||||
if (agreementInfo != null && !listL5.isEmpty()) {
|
||||
// 收集所有需要查询的typeId
|
||||
List<Long> typeIds = listL5.stream()
|
||||
.map(TypeTreeNode::getTypeId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 批量查询使用数量 - 性能优化关键点
|
||||
List<Type> batchResults = typeMapper.getNumListBatch(agreementInfo.getAgreementId(), typeIds);
|
||||
|
||||
// 转换为Map
|
||||
if (!CollectionUtils.isEmpty(batchResults)) {
|
||||
useNumMap = batchResults.stream()
|
||||
.filter(type -> type.getTypeId() != null && type.getUseNum() != null)
|
||||
.collect(Collectors.toMap(Type::getTypeId, Type::getUseNum));
|
||||
}
|
||||
}
|
||||
|
||||
// 设置使用数量
|
||||
for (TypeTreeNode node : listL5) {
|
||||
BigDecimal useNum = useNumMap.getOrDefault(node.getTypeId(), BigDecimal.ZERO);
|
||||
node.setUseNum(useNum);
|
||||
}
|
||||
List<Long> list4ParentIds = listL5.stream().map(TypeTreeNode::getParentId).collect(Collectors.toList());
|
||||
// 根据第四层parentId 查第三层类型
|
||||
listL3 = mapper.getUseTypeTreeL3(list4ParentIds);
|
||||
|
|
@ -1466,13 +1491,39 @@ public class MaterialLeaseInfoServiceImpl implements MaterialLeaseInfoService {
|
|||
// 原查询结果转换树形结构
|
||||
groupList = treeBuild.buildTree();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
AjaxResult.error("类型树-查询失败", e);
|
||||
log.error("getUseTypeTree方法执行失败", e);
|
||||
return AjaxResult.error("类型树-查询失败", e);
|
||||
} finally {
|
||||
long endTime = System.currentTimeMillis();
|
||||
long executionTime = endTime - startTime;
|
||||
log.info("getUseTypeTree方法执行完成,耗时:{}ms,返回数据量:{}", executionTime, groupList.size());
|
||||
}
|
||||
return AjaxResult.success(groupList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存班组查询 - 性能优化
|
||||
* @param teamName 班组名称
|
||||
* @return 班组信息
|
||||
*/
|
||||
@Cacheable(value = "teamCache", key = "#teamName", unless = "#result == null")
|
||||
public BmTeam getTeamByNameCached(String teamName) {
|
||||
BmTeam bmTeam = new BmTeam();
|
||||
bmTeam.setTeamName(teamName);
|
||||
return bmTeamMapper.selectByName(bmTeam);
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存协议信息查询 - 性能优化
|
||||
* @param bean 查询参数
|
||||
* @return 协议信息
|
||||
*/
|
||||
@Cacheable(value = "agreementCache", key = "#bean.proId + '_' + #bean.teamId", unless = "#result == null")
|
||||
public BmAgreementInfo getAgreementInfoCached(MaterialLeaseApplyInfo bean) {
|
||||
return materialLeaseInfoMapper.getAgreeId(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据班组和工程id查询领料机具
|
||||
* @param dto
|
||||
|
|
|
|||
|
|
@ -9,13 +9,16 @@ import com.bonus.common.log.enums.OperaType;
|
|||
import com.bonus.common.security.utils.SecurityUtils;
|
||||
import com.bonus.material.codeCollection.domain.WsMaInfo;
|
||||
import com.bonus.material.codeCollection.service.WsMaInfoService;
|
||||
import com.bonus.material.common.annotation.PreventRepeatSubmit;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 机具信息控制器
|
||||
|
|
@ -147,4 +150,26 @@ public class WsMaInfoController extends BaseController {
|
|||
public AjaxResult updateGadgetInfo(@RequestBody WsMaInfo info) {
|
||||
return service.updateGadgetInfo(info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入小工具信息模板
|
||||
*/
|
||||
@ApiOperation(value = "小工具导入模版下载")
|
||||
@PostMapping("/downLoad")
|
||||
public void downLoadExcelFile(){
|
||||
HttpServletResponse resp = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getResponse();
|
||||
service.downLoadTemplate(resp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 小工具信息导入
|
||||
* @param file
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "小工具信息导入")
|
||||
@PostMapping("/importData")
|
||||
public AjaxResult importData(MultipartFile file)
|
||||
{
|
||||
return service.importTbData(file);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.bonus.material.codeCollection.mapper;
|
||||
|
||||
import com.bonus.material.codeCollection.domain.WsMaInfo;
|
||||
import com.bonus.material.ma.domain.Type;
|
||||
import org.apache.ibatis.annotations.MapKey;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
|
@ -142,4 +143,18 @@ public interface WsMaInfoMapper {
|
|||
* @return 条数
|
||||
*/
|
||||
int updateGadgetInfo(WsMaInfo info);
|
||||
|
||||
/**
|
||||
* 根据级别查询所有匹配的记录
|
||||
* @param level
|
||||
* @param typeName
|
||||
* @return
|
||||
*/
|
||||
// 根据级别查询所有r匹配的记录
|
||||
List<Type> listByLevelAndName(@Param("level") String level, @Param("typeName") String typeName);
|
||||
|
||||
Type selectTypeRelation(@Param("parentLevel") String parentLevel,
|
||||
@Param("parentName") String parentName,
|
||||
@Param("childLevel") String childLevel,
|
||||
@Param("childName") String childName);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@ package com.bonus.material.codeCollection.service;
|
|||
|
||||
import com.bonus.common.core.web.domain.AjaxResult;
|
||||
import com.bonus.material.codeCollection.domain.WsMaInfo;
|
||||
import org.apache.ibatis.annotations.MapKey;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* WsMaInfoService
|
||||
|
|
@ -120,4 +119,17 @@ public interface WsMaInfoService {
|
|||
* @return
|
||||
*/
|
||||
AjaxResult updateGadgetInfo(WsMaInfo info);
|
||||
|
||||
/**
|
||||
* 小工具导入模版下载
|
||||
* @param resp
|
||||
*/
|
||||
void downLoadTemplate(HttpServletResponse resp);
|
||||
|
||||
/**
|
||||
* 导入小工具信息
|
||||
* @param file
|
||||
* @return
|
||||
*/
|
||||
AjaxResult importTbData(MultipartFile file);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,34 @@
|
|||
package com.bonus.material.codeCollection.service.impl;
|
||||
|
||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||
import com.bonus.common.biz.constant.GlobalConstants;
|
||||
import com.bonus.common.core.utils.poi.ExcelUtil;
|
||||
import com.bonus.common.core.web.domain.AjaxResult;
|
||||
import com.bonus.common.security.utils.SecurityUtils;
|
||||
import com.bonus.material.codeCollection.domain.WsMaInfo;
|
||||
import com.bonus.material.codeCollection.mapper.WsMaInfoMapper;
|
||||
import com.bonus.material.codeCollection.service.WsMaInfoService;
|
||||
import com.bonus.material.ma.domain.Type;
|
||||
import com.bonus.material.ma.domain.vo.ExceptionEnum;
|
||||
import com.bonus.material.ma.domain.vo.MaTypeVo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.hibernate.validator.internal.util.StringHelper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* {@code WsMaInfoServiceImpl}
|
||||
|
|
@ -281,4 +295,288 @@ public class WsMaInfoServiceImpl implements WsMaInfoService {
|
|||
return AjaxResult.error("更新失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 小工具导入模版下载
|
||||
* @param response
|
||||
*/
|
||||
@Override
|
||||
public void downLoadTemplate(HttpServletResponse response) {
|
||||
//模板名称
|
||||
String templateName = "机具检验标识信息导入模板.xls";
|
||||
OutputStream out = null;
|
||||
InputStream input =null;
|
||||
try {
|
||||
input = this.getClass().getClassLoader().getResourceAsStream("template/机具检验标识信息导入模板.xls");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.setHeader("content-Type", "application/vnd.ms-excel");
|
||||
response.setHeader("Content-Disposition",
|
||||
"attachment;filename=" + new String((templateName).getBytes(), "iso-8859-1"));
|
||||
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
|
||||
out = response.getOutputStream();
|
||||
// 缓冲区
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesToRead = -1;
|
||||
// 通过循环将读入内容输出到浏览器中
|
||||
while ((bytesToRead = input.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, bytesToRead);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage());
|
||||
} finally {
|
||||
IOUtils.closeQuietly(input);
|
||||
IOUtils.closeQuietly(out);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult importTbData(MultipartFile file) {
|
||||
String fileName = file.getOriginalFilename();
|
||||
if (fileName != null) {
|
||||
String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1);
|
||||
if (!GlobalConstants.XLSX.equalsIgnoreCase(fileExtension) && !GlobalConstants.XLS.equalsIgnoreCase(fileExtension)) {
|
||||
return AjaxResult.error("导入失败:文件后缀名不符合要求,必须为xlsx或xls结尾");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
InputStream inputStream = file.getInputStream();
|
||||
Workbook workbook = WorkbookFactory.create(inputStream);
|
||||
Sheet sheet = workbook.getSheetAt(0);
|
||||
|
||||
// 得到Excel的行数(跳过表头行)
|
||||
int totalRows = sheet.getPhysicalNumberOfRows();
|
||||
if (totalRows <= 1) {
|
||||
throw new IllegalArgumentException("导入失败:Excel文件中没有数据,请检查后重新导入");
|
||||
}
|
||||
|
||||
// 读取表头行(第一行)
|
||||
Row headerRow = sheet.getRow(1);
|
||||
if (headerRow == null) {
|
||||
throw new IllegalArgumentException("导入失败:文件中没有表头");
|
||||
}
|
||||
|
||||
// 验证表头
|
||||
validateHeader(headerRow);
|
||||
|
||||
List<WsMaInfo> wsMaInfos = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
int failCount = 0;
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
|
||||
// 从第二行开始读取数据(索引1)
|
||||
for (int rowNum = 2; rowNum < totalRows; rowNum++) {
|
||||
Row row = sheet.getRow(rowNum);
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
WsMaInfo wsMaInfo = parseRowToWsMaInfo(row);
|
||||
if (wsMaInfo != null) {
|
||||
wsMaInfos.add(wsMaInfo);
|
||||
// 新增操作
|
||||
wsMaInfo.setOptUser(SecurityUtils.getLoginUser().getSysUser().getNickName());
|
||||
mapper.addWsMaInfoData(wsMaInfo);
|
||||
successCount++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
failCount++;
|
||||
errorMessages.add("第 " + (rowNum + 1) + " 行数据解析失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 处理结果返回
|
||||
if (failCount == 0) {
|
||||
return AjaxResult.success("导入成功,共导入 " + successCount + " 条数据");
|
||||
} else {
|
||||
String errorMsg = "导入完成,成功 " + successCount + " 条,失败 " + failCount + " 条。";
|
||||
if (!errorMessages.isEmpty()) {
|
||||
errorMsg += "错误信息:" + String.join("; ", errorMessages);
|
||||
}
|
||||
return AjaxResult.error(errorMsg);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
log.error("导入文件读取失败", e);
|
||||
return AjaxResult.error("导入失败:文件读取异常");
|
||||
} catch (IllegalArgumentException e) {
|
||||
return AjaxResult.error(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("导入过程发生异常", e);
|
||||
return AjaxResult.error("导入失败:系统异常");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证表头格式
|
||||
*/
|
||||
private void validateHeader(Row headerRow) {
|
||||
String[] expectedHeaders = {
|
||||
"序号", "机具名称", "规格型号", "机具编号", "本次检验时间",
|
||||
"下次检验时间", "检修员", "检验员", "联系方式", "结果"
|
||||
};
|
||||
|
||||
int cellCount = headerRow.getPhysicalNumberOfCells();
|
||||
if (cellCount < expectedHeaders.length) {
|
||||
throw new IllegalArgumentException("导入失败:表头列数不足,请检查导入模板");
|
||||
}
|
||||
|
||||
for (int i = 0; i < expectedHeaders.length; i++) {
|
||||
Cell cell = headerRow.getCell(i);
|
||||
if (cell == null) {
|
||||
throw new IllegalArgumentException("导入失败:第 " + (i + 1) + " 列表头为空");
|
||||
}
|
||||
|
||||
String headerValue = getCellValueAsString(cell).trim();
|
||||
if (!expectedHeaders[i].equals(headerValue)) {
|
||||
throw new IllegalArgumentException("导入失败:第 " + (i + 1) + " 列表头 '" + headerValue +
|
||||
"' 与预期 '" + expectedHeaders[i] + "' 不符");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析单行数据到WsMaInfo对象
|
||||
*/
|
||||
private WsMaInfo parseRowToWsMaInfo(Row row) {
|
||||
WsMaInfo wsMaInfo = new WsMaInfo();
|
||||
|
||||
// 机具名称
|
||||
String maName = getCellValueAsString(row.getCell(1));
|
||||
if (StringHelper.isNullOrEmptyString(maName)){
|
||||
throw new IllegalArgumentException("机具名称不能为空");
|
||||
}
|
||||
wsMaInfo.setMaName(maName);
|
||||
|
||||
// 规格型号
|
||||
String maModel = getCellValueAsString(row.getCell(2));
|
||||
if (StringHelper.isNullOrEmptyString(maModel)){
|
||||
throw new IllegalArgumentException("规格型号不能为空");
|
||||
}
|
||||
wsMaInfo.setMaModel(maModel);
|
||||
|
||||
// 机具编号
|
||||
String maCode = getCellValueAsString(row.getCell(3));
|
||||
if (StringUtils.isEmpty(maCode)) {
|
||||
throw new IllegalArgumentException("机具编号不能为空");
|
||||
}
|
||||
wsMaInfo.setMaCode(maCode);
|
||||
|
||||
// 本次检验时间
|
||||
String thisCheckTime = getCellValueAsString(row.getCell(4));
|
||||
if (!isValidDate(thisCheckTime)) {
|
||||
throw new IllegalArgumentException("本次检验时间格式不正确");
|
||||
}
|
||||
wsMaInfo.setThisCheckTime(thisCheckTime);
|
||||
|
||||
// 下次检验时间
|
||||
String nextCheckTime = getCellValueAsString(row.getCell(5));
|
||||
if (!isValidDate(nextCheckTime)) {
|
||||
throw new IllegalArgumentException("下次检验时间格式不正确");
|
||||
}
|
||||
wsMaInfo.setNextCheckTime(nextCheckTime);
|
||||
|
||||
// 检修员
|
||||
wsMaInfo.setRepairMan(getCellValueAsString(row.getCell(6)));
|
||||
|
||||
// 检验员
|
||||
wsMaInfo.setCheckMan(getCellValueAsString(row.getCell(7)));
|
||||
|
||||
// 联系方式
|
||||
wsMaInfo.setPhone(getCellValueAsString(row.getCell(8)));
|
||||
|
||||
// 结果
|
||||
String result = getCellValueAsString(row.getCell(9));
|
||||
if (!"合格".equals(result) && !"不合格".equals(result)) {
|
||||
throw new IllegalArgumentException("检验结果必须是'合格'或'不合格'");
|
||||
}
|
||||
wsMaInfo.setResult(result);
|
||||
|
||||
// 验证设备类型和规格型号的层级关系
|
||||
validateTypeHierarchy(wsMaInfo, maName, maModel);
|
||||
|
||||
//判断该类型下编码是否已存在
|
||||
WsMaInfo info = mapper.getInfoByTypeAndModelAndCode(wsMaInfo);
|
||||
if (info != null){
|
||||
throw new IllegalArgumentException("该类型下编码已存在");
|
||||
}
|
||||
|
||||
return wsMaInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证设备类型和规格型号的层级关系
|
||||
*/
|
||||
/**
|
||||
* 通过关联查询验证层级关系(更高效)
|
||||
*/
|
||||
private void validateTypeHierarchy(WsMaInfo wsMaInfo, String typeName, String modelName) {
|
||||
// 使用关联查询直接验证层级关系
|
||||
Type relation = mapper.selectTypeRelation("3", typeName, "4", modelName);
|
||||
|
||||
if (relation == null) {
|
||||
throw new IllegalArgumentException("规格型号 '" + modelName + "' 不属于设备类型 '" + typeName + "' 或不存在");
|
||||
}
|
||||
|
||||
wsMaInfo.setModelId(String.valueOf(relation.getTypeId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新已存在的记录
|
||||
*/
|
||||
private void updateExistingRecord(WsMaInfo existing, WsMaInfo newData) {
|
||||
existing.setThisCheckTime(newData.getThisCheckTime());
|
||||
existing.setNextCheckTime(newData.getNextCheckTime());
|
||||
existing.setRepairMan(newData.getRepairMan());
|
||||
existing.setCheckMan(newData.getCheckMan());
|
||||
existing.setPhone(newData.getPhone());
|
||||
existing.setResult(newData.getResult());
|
||||
existing.setOptTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
||||
existing.setOptUser(SecurityUtils.getUsername());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单元格值的通用方法
|
||||
*/
|
||||
private String getCellValueAsString(Cell cell) {
|
||||
if (cell == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
switch (cell.getCellType()) {
|
||||
case STRING:
|
||||
return cell.getStringCellValue().trim();
|
||||
case NUMERIC:
|
||||
if (DateUtil.isCellDateFormatted(cell)) {
|
||||
return new SimpleDateFormat("yyyy-MM-dd").format(cell.getDateCellValue());
|
||||
} else {
|
||||
return String.valueOf((int) cell.getNumericCellValue());
|
||||
}
|
||||
case BOOLEAN:
|
||||
return String.valueOf(cell.getBooleanCellValue());
|
||||
case FORMULA:
|
||||
return cell.getCellFormula();
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证日期格式
|
||||
*/
|
||||
private boolean isValidDate(String dateStr) {
|
||||
if (StringUtils.isEmpty(dateStr)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
sdf.setLenient(false);
|
||||
sdf.parse(dateStr);
|
||||
return true;
|
||||
} catch (ParseException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.bonus.material.ma.mapper;
|
|||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.bonus.common.biz.domain.lease.LeaseOutDetails;
|
||||
import com.bonus.material.ma.domain.MaTypeHistory;
|
||||
|
|
@ -211,6 +212,14 @@ public interface TypeMapper {
|
|||
*/
|
||||
Type getNumList(Type type);
|
||||
|
||||
/**
|
||||
* 批量查询数量 - 性能优化
|
||||
* @param agreementId 协议ID
|
||||
* @param typeIds 类型ID列表
|
||||
* @return 类型使用数量列表
|
||||
*/
|
||||
List<Type> getNumListBatch(@Param("agreementId") Long agreementId, @Param("typeIds") List<Long> typeIds);
|
||||
|
||||
/**
|
||||
* 查询物资类型管理绑定的用户列表
|
||||
* @param type
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import com.bonus.common.core.utils.DateUtils;
|
|||
import com.bonus.common.core.utils.StringUtils;
|
||||
import com.bonus.common.security.utils.SecurityUtils;
|
||||
import com.bonus.material.back.mapper.BackApplyInfoMapper;
|
||||
import com.bonus.material.basic.domain.report.PurChaseReportInfo;
|
||||
import com.bonus.material.repair.domain.*;
|
||||
import com.bonus.material.repair.domain.vo.RepairAuditDetailsVO;
|
||||
import com.bonus.material.repair.domain.vo.RepairHomeInfo;
|
||||
|
|
@ -28,7 +27,6 @@ import com.bonus.material.task.domain.TmTaskAgreement;
|
|||
import com.bonus.material.task.mapper.TmTaskAgreementMapper;
|
||||
import com.bonus.material.task.mapper.TmTaskMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
|
@ -910,8 +908,13 @@ public class RepairAuditDetailsServiceImpl implements IRepairAuditDetailsService
|
|||
private Long insertScrapTt() {
|
||||
Long newTask = null;
|
||||
int thisMonthMaxOrder = taskMapper.getMonthMaxOrderByDate(DateUtils.getCurrentYear(), DateUtils.getCurrentMonth(), TmTaskTypeEnum.TM_TASK_SCRAP.getTaskTypeId());
|
||||
// 生成修饰入库单号
|
||||
// 生成报废单号
|
||||
String code = genderBfTaskCode(thisMonthMaxOrder);
|
||||
// 根据单号查询该任务是否存在
|
||||
TmTask task = taskMapper.selectTaskByCode(code);
|
||||
if (task != null) {
|
||||
throw new RuntimeException("该审核任务正在进行中,请勿重复提交!");
|
||||
}
|
||||
TmTask tmTask = new TmTask(null, TmTaskTypeEnum.TM_TASK_SCRAP.getTaskTypeId(), ScrapTaskStatusEnum.SCRAP_TASK_NO_FINISHED.getStatus(),
|
||||
null,thisMonthMaxOrder + 1, code);
|
||||
tmTask.setCreateTime(DateUtils.getNowDate());
|
||||
|
|
@ -963,6 +966,11 @@ public class RepairAuditDetailsServiceImpl implements IRepairAuditDetailsService
|
|||
null,thisMonthMaxOrder + 1, code);
|
||||
tmTask.setCreateTime(DateUtils.getNowDate());
|
||||
tmTask.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
|
||||
// 根据code查询此任务单号是否存在
|
||||
TmTask task = taskMapper.selectTaskByCode(code);
|
||||
if (task != null) {
|
||||
throw new RuntimeException("该审核任务正在进行中,请勿重复提交!");
|
||||
}
|
||||
// 插入任务
|
||||
int taskId = taskMapper.insertTmTask(tmTask);
|
||||
// 如果插入成功且返回的 taskId 大于 0
|
||||
|
|
|
|||
|
|
@ -448,6 +448,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
</update>
|
||||
|
||||
<update id="updateBoxStatus">
|
||||
update bm_qrcode_box set box_status = 5 where box_id = #{boxId}
|
||||
update bm_qrcode_box set box_status = 6 where box_id = #{boxId}
|
||||
</update>
|
||||
</mapper>
|
||||
|
|
|
|||
|
|
@ -122,7 +122,8 @@
|
|||
|
||||
</select>
|
||||
<select id="getGadgetList" resultType="com.bonus.material.codeCollection.domain.WsMaInfo">
|
||||
SELECT id,
|
||||
SELECT
|
||||
id,
|
||||
ma_name AS maName,
|
||||
ma_model AS maModel,
|
||||
ma_code AS maCode,
|
||||
|
|
@ -132,8 +133,8 @@
|
|||
check_man AS checkMan,
|
||||
phone,
|
||||
result
|
||||
FROM ws_ma_info wmi
|
||||
WHERE 1=1
|
||||
FROM ws_ma_info FORCE INDEX (idx_ws_ma_info_basic)
|
||||
WHERE ma_name IS NOT NULL
|
||||
<if test="keyWord != null and keyWord != ''">
|
||||
and ( ma_name like concat('%', #{keyWord}, '%') or
|
||||
ma_model like concat('%', #{keyWord}, '%') or
|
||||
|
|
@ -150,6 +151,7 @@
|
|||
)
|
||||
]]>
|
||||
</if>
|
||||
ORDER BY ma_name, ma_model, this_check_time DESC
|
||||
</select>
|
||||
<select id="getGadgetInfo" resultType="com.bonus.material.codeCollection.domain.WsMaInfo">
|
||||
SELECT wmi.id,
|
||||
|
|
@ -202,6 +204,24 @@
|
|||
and ma_model = #{maModel}
|
||||
and ma_code = #{maCode}
|
||||
</select>
|
||||
<select id="listByLevelAndName" resultType="com.bonus.material.ma.domain.Type">
|
||||
SELECT type_id AS typeId, type_name as typeName, level, parent_id as parentId
|
||||
FROM ma_type
|
||||
WHERE level = #{level}
|
||||
AND type_name = #{typeName}
|
||||
</select>
|
||||
<select id="selectTypeRelation" resultType="com.bonus.material.ma.domain.Type">
|
||||
SELECT
|
||||
mt3.type_id as parentId,
|
||||
mt4.type_id as typeId
|
||||
FROM ma_type mt3
|
||||
INNER JOIN ma_type mt4 ON mt3.type_id = mt4.parent_id
|
||||
WHERE mt3.level = #{parentLevel}
|
||||
AND mt3.type_name = #{parentName}
|
||||
AND mt4.level = #{childLevel}
|
||||
AND mt4.type_name = #{childName}
|
||||
LIMIT 1
|
||||
</select>
|
||||
<insert id="insert" parameterType="com.bonus.material.codeCollection.domain.WsMaInfo" useGeneratedKeys="true"
|
||||
keyProperty="id">
|
||||
INSERT INTO ws_ma_info (ma_name, ma_model, ma_code, supplier, this_check_time, next_check_time,
|
||||
|
|
|
|||
|
|
@ -1088,6 +1088,25 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
mt.type_id
|
||||
</select>
|
||||
|
||||
<!-- 批量查询数量 - 性能优化 -->
|
||||
<select id="getNumListBatch" resultType="com.bonus.material.ma.domain.Type">
|
||||
SELECT
|
||||
mt.type_id as typeId,
|
||||
SUM( CASE WHEN sai.agreement_id = #{agreementId} AND sai.STATUS = '0' THEN sai.num ELSE 0 END ) AS useNum
|
||||
FROM
|
||||
ma_type mt
|
||||
LEFT JOIN clz_slt_agreement_info sai ON mt.type_id = sai.type_id
|
||||
WHERE
|
||||
mt.type_id IN
|
||||
<foreach collection="typeIds" item="typeId" open="(" separator="," close=")">
|
||||
#{typeId}
|
||||
</foreach>
|
||||
AND EXISTS ( SELECT 1 FROM clz_slt_agreement_info sai2 WHERE sai2.type_id = mt.type_id AND sai2.agreement_id = #{agreementId}
|
||||
AND sai2.STATUS = '0' and sai2.num > 0)
|
||||
GROUP BY
|
||||
mt.type_id
|
||||
</select>
|
||||
|
||||
<select id="getUserList" resultType="com.bonus.material.ma.domain.vo.MaTypeVo">
|
||||
SELECT DISTINCT
|
||||
su.user_id as keeperUserId,
|
||||
|
|
|
|||
|
|
@ -1197,33 +1197,32 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<!-- 已结算协议:租赁期间与查询区间有交集 -->
|
||||
(bai.is_slt = 1 AND (
|
||||
<!-- 情况1:领料时间在查询区间内 -->
|
||||
(sai.start_time IS NOT NULL AND sai.start_time BETWEEN #{startDate} AND #{endDate})
|
||||
(sai.start_time IS NOT NULL AND DATE(sai.start_time) >= #{startDate} AND DATE(sai.start_time) <= #{endDate})
|
||||
OR
|
||||
<!-- 情况2:退料时间在查询区间内 -->
|
||||
(sai.end_time IS NOT NULL AND sai.end_time BETWEEN #{startDate} AND #{endDate})
|
||||
(sai.end_time IS NOT NULL AND DATE(sai.end_time) >= #{startDate} AND DATE(sai.end_time) <= #{endDate})
|
||||
OR
|
||||
<!-- 情况3:结算时间在查询区间内 -->
|
||||
(sai.slt_time IS NOT NULL AND sai.slt_time BETWEEN #{startDate} AND #{endDate})
|
||||
(sai.slt_time IS NOT NULL AND DATE(sai.slt_time) >= #{startDate} AND DATE(sai.slt_time) <= #{endDate})
|
||||
OR
|
||||
<!-- 情况4:跨区间租赁(领料在区间前,退料/结算在区间后) -->
|
||||
(sai.start_time IS NOT NULL AND sai.start_time < #{startDate} AND
|
||||
((sai.end_time IS NOT NULL AND sai.end_time > #{endDate}) OR
|
||||
(sai.slt_time IS NOT NULL AND sai.slt_time > #{endDate})))
|
||||
(sai.start_time IS NOT NULL AND DATE(sai.start_time) < #{startDate} AND
|
||||
((sai.end_time IS NOT NULL AND DATE(sai.end_time) > #{endDate}) OR (sai.slt_time IS NOT NULL AND DATE(sai.slt_time) > #{endDate})))
|
||||
))
|
||||
OR
|
||||
<!-- 未结算协议:租赁期间与查询区间有交集 -->
|
||||
((bai.is_slt = 0 OR bai.is_slt IS NULL) AND (
|
||||
<!-- 情况1:领料时间在查询区间内 -->
|
||||
(sai.start_time IS NOT NULL AND sai.start_time BETWEEN #{startDate} AND #{endDate})
|
||||
(sai.start_time IS NOT NULL AND DATE(sai.start_time) >= #{startDate} AND DATE(sai.start_time) <= #{endDate})
|
||||
OR
|
||||
<!-- 情况2:退料时间在查询区间内 -->
|
||||
(sai.end_time IS NOT NULL AND sai.end_time BETWEEN #{startDate} AND #{endDate})
|
||||
(sai.end_time IS NOT NULL AND DATE(sai.end_time) >= #{startDate} AND DATE(sai.end_time) <= #{endDate})
|
||||
OR
|
||||
<!-- 情况3:跨区间租赁(领料在区间前,退料在区间后或未退料) -->
|
||||
(sai.start_time IS NOT NULL AND sai.start_time < #{startDate} AND (sai.end_time IS NULL OR sai.end_time > #{endDate}))
|
||||
(sai.start_time IS NOT NULL AND DATE(sai.start_time) < #{startDate} AND (sai.end_time IS NULL OR DATE(sai.end_time) > #{endDate}))
|
||||
OR
|
||||
<!-- 情况4:设备状态为在用(未退料)且领料时间不晚于查询结束时间 -->
|
||||
(sai.status = '0' AND sai.start_time IS NOT NULL AND sai.start_time <= #{endDate})
|
||||
(sai.status = '0' AND sai.start_time IS NOT NULL AND DATE(sai.start_time) <= #{endDate})
|
||||
))
|
||||
)
|
||||
</where>
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue