Commit 0c55e268 张少辉

1.库存缺料信息优化

1 个父辈 46475c29
......@@ -2,29 +2,44 @@ package com.neotel.smfcore.core.message.rest;
import cn.hutool.core.util.ObjectUtil;
import com.neotel.smfcore.common.bean.PageData;
import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.common.utils.DateUtil;
import com.neotel.smfcore.common.utils.QueryHelp;
import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.barcode.utils.CodeResolve;
import com.neotel.smfcore.core.language.util.MessageUtils;
import com.neotel.smfcore.core.message.rest.bean.dto.MessageDto;
import com.neotel.smfcore.core.message.rest.bean.mapstruct.MessageMapper;
import com.neotel.smfcore.core.message.rest.bean.query.MessageCriteria;
import com.neotel.smfcore.core.message.service.manager.IMessageManager;
import com.neotel.smfcore.core.message.service.po.Message;
import com.neotel.smfcore.core.system.service.manager.IDataLogManager;
import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
@Slf4j
@RestController
......@@ -37,6 +52,12 @@ public class MessageController {
@Autowired
MessageMapper messageMapper;
@Autowired
private CodeResolve codeResolve;
@Autowired
private IDataLogManager dataLogManager;
@ApiOperation("导出消息列表")
@GetMapping(value = "/download")
public void download(HttpServletResponse response, MessageCriteria criteria, HttpServletRequest request) throws Exception {
......@@ -70,4 +91,48 @@ public class MessageController {
List<String> typeList=messageManager.findDeviceNameList();
return typeList;
}
@ApiOperation("根据barcode获取最近一天的异常信息")
@RequestMapping(value = "/getMessageByCode")
@AnonymousAccess
public ResultBean getMessageByCode(@RequestBody Map<String, String> paramMap) {
String code = paramMap.get("code");
Barcode barcode = null;
try {
barcode = codeResolve.resolveOneValideBarcode(code);
} catch (ValidateException e) {
return ResultBean.newErrorResult(-1, e.getMsgKey(), e.getMessage(), e.getMsgParam());
}
List<String> resultList = new ArrayList<>();
Pattern pattern = Pattern.compile(barcode.getBarcode(), Pattern.CASE_INSENSITIVE);
long oneDayMillis = 24 * 60 * 60 * 1000L; // 1天的毫秒数(加L避免int溢出)
Date currentTime = new Date(); // 当前时间
Date oneDayAgo = new Date(System.currentTimeMillis() - oneDayMillis); // 当前时间减1天
Criteria c = Criteria.where("msg")
.regex(pattern) // msg字段匹配条码正则(忽略大小写)
.and("createDate")
.gte(oneDayAgo) // createDate >= 1天前
.lte(currentTime); // createDate <= 当前时间
Query q = new Query(c);
q.with(Sort.by(Sort.Direction.DESC, "createDate"));
List<Message> messageList = messageManager.findByQuery(q);
if (messageList != null && !messageList.isEmpty()) {
for (Message message : messageList) {
resultList.add(message.getMsg()+",发生时间点:"+ DateUtil.toDateString(message.getCreateDate(),"yyyy-MM-dd HH:mm:ss"));
}
} else {
DataLog lastTask = dataLogManager.findLastTask(barcode.getBarcode());
if (lastTask != null && lastTask.isCheckOutTask()) {
if (lastTask.isCancel()) {
resultList.add("最后一条为出库任务,任务被取消了,发生时间点:" + DateUtil.toDateString(lastTask.getUpdateDate(), "yyyy-MM-dd HH:mm:ss"));
} else {
resultList.add("最后一条为出库任务了,请判断是否正常出库完成,是否扫码异常等,发生时间点:" + DateUtil.toDateString(lastTask.getUpdateDate(), "yyyy-MM-dd HH:mm:ss"));
}
} else {
resultList.add("未找到对应的异常信息,请判断是否入库扫码失败等,重新入库");
}
}
return ResultBean.newOkResult(resultList);
}
}
......@@ -585,6 +585,8 @@ public class LiteOrderCache {
}
}
//禁用的ri
List<String> disableRiList = new ArrayList<>();
Collection<String> excludePosIds = excludeOutPosIds();
......@@ -673,7 +675,6 @@ public class LiteOrderCache {
if (pos == null) {
break;
}
boolean disable = false;
try {
excludePosIds.add(pos.getId());
......@@ -749,7 +750,7 @@ public class LiteOrderCache {
for (String batchModel : modelList) {
List<String> batchCheckReel = lizhenApi.batchCheckReel(Arrays.asList(pos.getBarcode()), "",batchModel);
if (batchCheckReel != null && !batchCheckReel.isEmpty()){
disable = true;
disableRiList.addAll(batchCheckReel);
throw new ValidateException("",pos.getBarcode().getBarcode()+"被禁用,库位为:"+pos.getPosName());
}
}
......@@ -763,6 +764,12 @@ public class LiteOrderCache {
} while (pos == null);
}
if (pos == null) {
String shortageReason = "没找到可用库存";
if (disableRiList != null && !disableRiList.isEmpty()) {
shortageReason = shortageReason + ",库存有禁用料:"+ String.join(",",disableRiList);
}
orderItem.setShortageReason(shortageReason);
liteOrderItemManager.save(orderItem);
// log.error("未找到可以出库的物料[" + partNumber + "]");
break;
} else {
......
......@@ -648,6 +648,7 @@ public class OrderController {
headerList.add(Arrays.asList("已出盘数"));
headerList.add(Arrays.asList("已出物料"));
headerList.add(Arrays.asList("已出PN"));
headerList.add(Arrays.asList("缺料原因"));
List<List<Object>> dataList = new ArrayList<>();
for (LiteOrderItem orderItem : liteOrder.getOrderItems()) {
......@@ -690,6 +691,7 @@ public class OrderController {
data.add(orderItem.getOutReel());
data.add(orderItem.getOutPn());
data.add(orderItem.getShortageReason());
dataList.add(data);
}
FileUtil.downloadExcel(headerList,dataList,response);
......
......@@ -138,6 +138,8 @@ public class OrderItemDto {
private String outPn;
private String shortageReason;
//@ApiModelProperty("工单出库详情")
//private List<ItemOutDetail> outDetailList;
}
......@@ -254,6 +254,8 @@ public class LiteOrderItem extends BasePo implements Serializable ,Comparable<Li
private String outPn;
private String shortageReason;
public void setOutReelList(String reel) {
if (outReelList == null){
outReelList = new ArrayList<>();
......
......@@ -74,7 +74,7 @@ public class ReelConsumptionController {
List<String> lineList = cacheMap.keySet().stream().sorted().collect(Collectors.toList());
for (String line : lineList) {
headerList.add(Arrays.asList(line + "最小库存"));
headerList.add(Arrays.asList(line + "最大库存"));
//headerList.add(Arrays.asList(line + "最大库存"));
}
List<List<Object>> datas = new ArrayList<>();
for (int i = 0; i < 10; i++) {
......@@ -83,7 +83,7 @@ public class ReelConsumptionController {
dataList.add("分组"+i);
for (String line : lineList) {
dataList.add(i);
dataList.add(i+10);
//dataList.add(i+10);
}
datas.add(dataList);
}
......@@ -164,7 +164,7 @@ public class ReelConsumptionController {
}
reelConsumption.setReplaceGroup(value);
} else {
String maxInventory = header + "最大库存";
/* String maxInventory = header + "最大库存";
Integer maxIndex = headerMap.get(maxInventory);
if (maxIndex == null || maxIndex == -1) {
throw new ValidateException("smfcore.valueNotExist", "{0}[{1}]不存在", new String[]{maxInventory});
......@@ -175,7 +175,7 @@ public class ReelConsumptionController {
throw new ValidateException("smfcore.valueNotExist", "{0}[{1}]不存在", new String[]{maxInventory});
}
double maxValue = maxCell.getNumericCellValue();
double maxValue = maxCell.getNumericCellValue();*/
String minInventory = header + "最小库存";
Integer minIndex = headerMap.get(minInventory);
......@@ -191,7 +191,7 @@ public class ReelConsumptionController {
double minValue = cell.getNumericCellValue();
ReelConsumptionInventory inventory = new ReelConsumptionInventory();
inventory.setMax((int) maxValue);
inventory.setMax(0);
inventory.setMin((int) minValue);
Map<String, ReelConsumptionInventory> inventoryMap = reelConsumption.getInventoryMap();
inventoryMap.put(header, inventory);
......@@ -210,11 +210,15 @@ public class ReelConsumptionController {
@ApiOperation("获取列表信息")
@RequestMapping(value = "/list")
@AnonymousAccess
public PageData list(String partNumber, Pageable pageable) {
public PageData list(String partNumber,String replaceGroup, Pageable pageable) {
Query query = new Query();
if (StringUtils.isNotEmpty(partNumber)) {
query.addCriteria(Criteria.where("partNumber").is(partNumber));
}
if (StringUtils.isNotEmpty(replaceGroup)){
query.addCriteria(Criteria.where("replaceGroup").is(replaceGroup));
}
PageData<ReelConsumption> pageData = reelConsumptionManager.findByPage(query, pageable);
int totalElements = pageData.getTotalElements();
if (totalElements == 0) {
......@@ -458,7 +462,7 @@ public class ReelConsumptionController {
List<String> lineList = cacheMap.keySet().stream().sorted().collect(Collectors.toList());
for (String line : lineList) {
headerList.add(Arrays.asList(line + "最小库存"));
headerList.add(Arrays.asList(line + "最大库存"));
//headerList.add(Arrays.asList(line + "最大库存"));
}
// 3. 查询全部物料基础数据(不分页)
......@@ -490,7 +494,7 @@ public class ReelConsumptionController {
int min = inventory != null ? inventory.getMin() : 0;
int max = inventory != null ? inventory.getMax() : 0;
dataRow.add(min);
dataRow.add(max);
//dataRow.add(max);
}
}
datas.add(dataRow);
......
......@@ -4,6 +4,7 @@ import com.neotel.smfcore.common.bean.PageData;
import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.common.utils.Constants;
import com.neotel.smfcore.common.utils.FileUtil;
import com.neotel.smfcore.common.utils.QueryHelp;
import com.neotel.smfcore.common.utils.StringUtils;
import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.storage.bean.InventoryItem;
......@@ -12,12 +13,15 @@ import com.neotel.smfcore.custom.lizhen.innerBox.bean.ReelConsumption;
import com.neotel.smfcore.custom.lizhen.innerBox.bean.ReelConsumptionInventory;
import com.neotel.smfcore.custom.lizhen.innerBox.service.manager.IReelConsumptionManager;
import com.neotel.smfcore.custom.lizhen.report.bean.dto.TowerInventory;
import com.neotel.smfcore.custom.lizhen.report.bean.query.TowerInventoryQuery;
import com.neotel.smfcore.custom.lizhen.report.service.ITowerInventoryService;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
......@@ -38,39 +42,56 @@ public class TowerInventoryController {
@Autowired
private IReelConsumptionManager reelConsumptionManager;
//库存明细
@RequestMapping("/detail")
@AnonymousAccess
public PageData detail(String partNumber, Pageable pageable) {
@Autowired
private ITowerInventoryService towerInventoryService;
Query query = new Query();
if (StringUtils.isNotEmpty(partNumber)){
query.addCriteria(Criteria.where("partNumber").is(partNumber));
@Scheduled(fixedRate = 1000*60*2, initialDelay = 1000 * 30)
public void syncTowerInventoryData() {
try {
List<ReelConsumption> consumptionList = reelConsumptionManager.findByQuery(new Query());
if (consumptionList != null && !consumptionList.isEmpty()) {
log.info("开始同步 Tower 库存数据...");
List<TowerInventory> towerInventoryList = getTowerInventoryDetail(consumptionList);
for (TowerInventory towerInventory : towerInventoryList) {
TowerInventory oldTowerInventory = towerInventoryService.findOne(
new Query(Criteria.where("partNumber").is(towerInventory.getPartNumber())));
if (oldTowerInventory != null) {
towerInventory.setId(oldTowerInventory.getId());
towerInventoryService.save(towerInventory);
} else {
towerInventoryService.save(towerInventory);
}
}
log.info("结束同步 Tower 库存数据...");
}
} catch (Exception e) {
log.error("Tower 库存数据同步失败", e);
}
}
PageData<ReelConsumption> pageData = reelConsumptionManager.findByPage(query, pageable);
if (pageData.getTotalElements() == 0){
return new PageData<>(new ArrayList<>(),0);
}
List<TowerInventory> towerInventoryList = getTowerInventoryDetail(pageData.getContent());
return new PageData(towerInventoryList,pageData.getTotalElements());
//库存明细
@RequestMapping("/detail")
@AnonymousAccess
public PageData detail(TowerInventoryQuery towerInventoryQuery, Pageable pageable) {
Query query = QueryHelp.getQuery(towerInventoryQuery);
if (towerInventoryQuery.isShortage()){
query.addCriteria(Criteria.where("shortageDisks").lt(0));
}
PageData<TowerInventory> pageData = towerInventoryService.findByPage(query, pageable);
return pageData;
}
@RequestMapping("/detail/download")
@AnonymousAccess
public void detailDownload(String partNumber, HttpServletResponse response) {
public void detailDownload(TowerInventoryQuery towerInventoryQuery , HttpServletResponse response) {
Query query = new Query();
if (StringUtils.isNotEmpty(partNumber)){
query.addCriteria(Criteria.where("partNumber").is(partNumber));
}
List<ReelConsumption> consumptionList = reelConsumptionManager.findByQuery(query);
if (consumptionList == null){
consumptionList = new ArrayList<>();
Query query = QueryHelp.getQuery(towerInventoryQuery);
if (towerInventoryQuery.isShortage()){
query.addCriteria(Criteria.where("shortageDisks").gt(0));
}
List<TowerInventory> towerInventoryList = getTowerInventoryDetail(consumptionList);
List<TowerInventory> towerInventoryList = towerInventoryService.findByQuery(query);
if (towerInventoryList == null || towerInventoryList.isEmpty()) {
log.info("库存缺料报表无数据,不导出");
return;
......@@ -81,7 +102,7 @@ public class TowerInventoryController {
headers.add(Arrays.asList("料号"));
headers.add(Arrays.asList("替代料分组"));
headers.add(Arrays.asList("需求最小库存盘数"));
headers.add(Arrays.asList("需求最大库存盘数"));
//headers.add(Arrays.asList("需求最大库存盘数"));
headers.add(Arrays.asList("当前库存盘数"));
headers.add(Arrays.asList("缺料盘数"));
headers.add(Arrays.asList("缺料百分比"));
......@@ -115,10 +136,10 @@ public class TowerInventoryController {
rowData.add(inv.getPartNumber());
rowData.add(inv.getReplaceGroup());
rowData.add(inv.getMinNeedInventory());
rowData.add(inv.getMaxNeedInventory());
//rowData.add(inv.getMaxNeedInventory());
rowData.add(inv.getCurrentInventory());
rowData.add(inv.getShortageDisks());
rowData.add(inv.getShortagePercentage());
rowData.add(String.format("%.2f%%", inv.getShortagePercentage()));
// 动态列(按表头顺序)
/*Map<String, TowerInventory.MaxAndMinInventory> map = inv.getMaxAndMinInventoryMap();
......@@ -230,18 +251,18 @@ public class TowerInventoryController {
count = count + allPartNumberInventory.getOrDefault(replacePartNumber, 0);
}
towerInventory.setCurrentInventory(allPartNumberInventory.getOrDefault(towerInventory.getPartNumber(), 0));
towerInventory.setCurrentInventory(count);
// 缺料计算
if (minNeedInventory == 0) {
towerInventory.setShortageDisks(0);
towerInventory.setShortagePercentage("0%");
towerInventory.setShortagePercentage(0.0);
} else {
int shortageDisks = minNeedInventory - count;
int shortageDisks = count - minNeedInventory;
towerInventory.setShortageDisks(shortageDisks);
double percentage = (double) shortageDisks / minNeedInventory * 100;
towerInventory.setShortagePercentage(String.format("%.2f%%", percentage));
towerInventory.setShortagePercentage(percentage);
}
}
......
package com.neotel.smfcore.custom.lizhen.report.bean.dto;
import com.neotel.smfcore.common.base.BasePo;
import lombok.Data;
import java.io.Serializable;
import java.util.Map;
@Data
public class TowerInventory {
public class TowerInventory extends BasePo implements Serializable {
private String partNumber;
......@@ -21,7 +23,7 @@ public class TowerInventory {
private int shortageDisks; //缺料盘数
private String shortagePercentage; //缺料百分比
private double shortagePercentage; //缺料百分比
@Data
......
package com.neotel.smfcore.custom.lizhen.report.bean.query;
import com.neotel.smfcore.common.annotation.QueryCondition;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("查询条件")
public class TowerInventoryQuery {
@QueryCondition(blurry = "partNumber")
@ApiModelProperty("料号")
private String partNumber;
@QueryCondition(blurry = "replaceGroup")
@ApiModelProperty("料号")
private String replaceGroup;
private boolean shortage = true;
}
package com.neotel.smfcore.custom.lizhen.report.dao;
import com.neotel.smfcore.common.base.IBaseDao;
public interface ITowerInventoryDao extends IBaseDao {
}
package com.neotel.smfcore.custom.lizhen.report.dao.impl;
import com.neotel.smfcore.common.base.AbstractBaseDao;
import com.neotel.smfcore.custom.lizhen.report.bean.dto.TowerInventory;
import com.neotel.smfcore.custom.lizhen.report.dao.ITowerInventoryDao;
import org.springframework.stereotype.Service;
@Service
public class TowerInventoryDaoImpl extends AbstractBaseDao implements ITowerInventoryDao {
@Override
public Class getEntityClass() {
return TowerInventory.class;
}
}
package com.neotel.smfcore.custom.lizhen.report.service;
import com.neotel.smfcore.common.base.IBaseManager;
import com.neotel.smfcore.custom.lizhen.report.bean.dto.TowerInventory;
import org.springframework.data.mongodb.core.query.Query;
public interface ITowerInventoryService extends IBaseManager<TowerInventory> {
TowerInventory findOne(Query partNumber);
}
package com.neotel.smfcore.custom.lizhen.report.service.impl;
import com.neotel.smfcore.common.bean.PageData;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.custom.lizhen.report.bean.dto.TowerInventory;
import com.neotel.smfcore.custom.lizhen.report.dao.ITowerInventoryDao;
import com.neotel.smfcore.custom.lizhen.report.service.ITowerInventoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
@Service
public class TowerInventoryServiceImpl implements ITowerInventoryService {
@Autowired
private ITowerInventoryDao towerInventoryDao;
@Override
public TowerInventory get(String id) {
return null;
}
@Override
public TowerInventory save(TowerInventory object) throws ValidateException {
return towerInventoryDao.save(object);
}
@Override
public void delete(TowerInventory object) throws ValidateException {
}
@Override
public PageData<TowerInventory> findByPage(Query query, Pageable pageable) {
int count = towerInventoryDao.countByQuery(query);
List list = towerInventoryDao.findByQuery(query, pageable);
return new PageData<>(list,count);
}
@Override
public List<TowerInventory> findByQuery(Query query) {
return towerInventoryDao.findByQuery(query);
}
@Override
public TowerInventory findOne(Query query) {
return towerInventoryDao.findOne(query);
}
}
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!