Commit 7cda0b7a sunke

Merge remote-tracking branch 'origin/master'

2 个父辈 f797b3aa a4c257e6
...@@ -147,6 +147,18 @@ public class DateUtil { ...@@ -147,6 +147,18 @@ public class DateUtil {
c.add(Calendar.DAY_OF_YEAR, days); c.add(Calendar.DAY_OF_YEAR, days);
return c.getTime(); return c.getTime();
} }
/**
* 日期+天数
* @param date
* @param seconds
* @return
*/
public static Date addSeconds(Date date, int seconds){
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(Calendar.SECOND, seconds);
return c.getTime();
}
public static Date getMinDate(Date date0, Date date1){ public static Date getMinDate(Date date0, Date date1){
return date0.before(date1)? date0 : date1; return date0.before(date1)? date0 : date1;
......
...@@ -3,16 +3,20 @@ package com.neotel.smfcore.core.order; ...@@ -3,16 +3,20 @@ package com.neotel.smfcore.core.order;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.neotel.smfcore.common.bean.ResultBean; import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.common.exception.ValidateException; import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.common.utils.Constants;
import com.neotel.smfcore.core.barcode.service.po.Barcode; import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.device.bean.StatusBean;
import com.neotel.smfcore.core.device.enums.OP; import com.neotel.smfcore.core.device.enums.OP;
import com.neotel.smfcore.core.device.enums.OP_STATUS; import com.neotel.smfcore.core.device.enums.OP_STATUS;
import com.neotel.smfcore.core.device.util.DataCache; import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.order.enums.LITEORDER_STATUS;
import com.neotel.smfcore.core.order.enums.ORDER_COLOR; import com.neotel.smfcore.core.order.enums.ORDER_COLOR;
import com.neotel.smfcore.core.order.service.dao.ILiteOrderDao; import com.neotel.smfcore.core.order.service.dao.ILiteOrderDao;
import com.neotel.smfcore.core.order.service.manager.ILiteOrderItemManager; import com.neotel.smfcore.core.order.service.manager.ILiteOrderItemManager;
import com.neotel.smfcore.core.order.service.manager.ILiteOrderManager; import com.neotel.smfcore.core.order.service.manager.ILiteOrderManager;
import com.neotel.smfcore.core.order.service.po.LiteOrder; import com.neotel.smfcore.core.order.service.po.LiteOrder;
import com.neotel.smfcore.core.order.service.po.LiteOrderItem; import com.neotel.smfcore.core.order.service.po.LiteOrderItem;
import com.neotel.smfcore.core.storage.enums.CHECKOUT_TYPE;
import com.neotel.smfcore.core.storage.service.manager.IStoragePosManager; import com.neotel.smfcore.core.storage.service.manager.IStoragePosManager;
import com.neotel.smfcore.core.storage.service.po.Storage; import com.neotel.smfcore.core.storage.service.po.Storage;
import com.neotel.smfcore.core.storage.service.po.StoragePos; import com.neotel.smfcore.core.storage.service.po.StoragePos;
...@@ -71,6 +75,9 @@ public class LiteOrderCache implements ITaskListener { ...@@ -71,6 +75,9 @@ public class LiteOrderCache implements ITaskListener {
ORDER_COLOR nextColor = ORDER_COLOR.nextColor(currentColors); ORDER_COLOR nextColor = ORDER_COLOR.nextColor(currentColors);
//其他出库模式一次性全部生成任务 //其他出库模式一次性全部生成任务
List<StoragePos> lockPosList = storagePosManager.findLockPos(liteOrder.getOrderNo()); List<StoragePos> lockPosList = storagePosManager.findLockPos(liteOrder.getOrderNo());
if(lockPosList==null){
throw new ValidateException("未找到锁定库位");
}
int taskReelCount = 0; int taskReelCount = 0;
for (StoragePos lockPos : lockPosList) { for (StoragePos lockPos : lockPosList) {
Storage storage = dataCache.getStorageById(lockPos.getStorageId()); Storage storage = dataCache.getStorageById(lockPos.getStorageId());
...@@ -183,4 +190,149 @@ public class LiteOrderCache implements ITaskListener { ...@@ -183,4 +190,149 @@ public class LiteOrderCache implements ITaskListener {
} }
} }
} }
/**
* 锁定物料
*/
public synchronized String checkOutLiteOrder(String orderNo, boolean outBom) {
LiteOrder cacheOrder = liteOrderMap.get(orderNo);
if (cacheOrder != null && !cacheOrder.isTaskFinished() && !cacheOrder.isNew()) {
log.info("工单[" + orderNo + "]正在执行");
return "order.out.executing";
}
if (cacheOrder == null) {
cacheOrder = liteOrderManager.findByOrderNo(orderNo);
}
if (cacheOrder == null) {
return "order.out.notFound";
}
//设置颜色
Set<String> currentColors = new HashSet<>();
for (DataLog dataLog : taskService.getQueueTasks()) {
currentColors.add(dataLog.getLightColor());
}
ORDER_COLOR nextColor = ORDER_COLOR.nextColor(currentColors);
if (nextColor == null) {
log.info("执行工单[" + orderNo + "] outBom=" + outBom + "时,已达最大可执行工单数");
return "order.out.maxOrder";
}
log.info("开始执行工单[" + orderNo + "] outBom=" + outBom);
cacheOrder.setTaskReelCount(0);
cacheOrder.setTaskFinishedTime(-1);
cacheOrder.setFinishedReelCount(0);
if (outBom) {
cacheOrder.setStatus(LITEORDER_STATUS.BOM);
} else {
cacheOrder.setStatus(LITEORDER_STATUS.TAILS);
}
//liteOrderMap.put(cacheOrder.getOrderNo(), cacheOrder);
int taskReelCount = 0;
CHECKOUT_TYPE checkoutType = dataCache.getCheckOutType();
List<String> availableStorageIds = new ArrayList<>();
for (Storage storage : dataCache.getAllStorage().values()) {
//默认所有料仓可用
// StatusBean statusBean =dataCache. getStatus(storage.getCid());
// if (statusBean.isAvailable())
{
availableStorageIds.add(storage.getId());
}
}
//其他出库模式一次性全部生成任务
for (LiteOrderItem orderItem : cacheOrder.getOrderItems()) {
//剩余未出数量
Float totalNum = orderItem.getNeedNum() * cacheOrder.getOrderTimes();
int remainNum = totalNum.intValue() - orderItem.getOutNum();
//此PN未完成
if (remainNum > 0) {
if (outBom) {
//套料出库,设置剩余数量为1,这样就只会出一盘
remainNum = 1;
}
int assignNum = 0;
while (assignNum < remainNum) {
Collection<String> excludePosIds = excludePosIds();
String partNumber = orderItem.getPn();
StoragePos pos = storagePosManager.findPartNumberInStorages(availableStorageIds, partNumber, excludePosIds, checkoutType);
if (pos == null) {
log.error("未找到可以出库的物料[" + partNumber + "]");
break;
} else {
assignNum = assignNum + pos.getBarcode().getAmount();
taskReelCount = taskReelCount + 1;
log.info("工单[" + orderNo + "],任务数[" + taskReelCount + "]出库位置仓位【" + pos.getPosName() + "】RI=[" + pos.getBarcode().getBarcode() + "] PN=[" + partNumber + "] num:" + pos.getBarcode().getAmount());
DataLog task = newTask(pos) ;
task.setSourceId(cacheOrder.getId());
task.setSourceName(cacheOrder.getOrderNo());
task.setSubSourceId(orderItem.getId());
task.setSubSourceInfo(orderItem.getFeederInfo());
task.setType(OP.CHECKOUT);
task.setLightColor(nextColor.getRgb());
task.setStatus(OP_STATUS.WAIT.name());
// task = dataLogDao.save(task);
taskService.addTaskToExecute(task);
}
}
}
}
cacheOrder.setTaskReelCount(taskReelCount);
log.info("工单[" + orderNo + "]任务分配结束,任务数[" + taskReelCount + "]");
//有需要出库的
if (taskReelCount <= 0) {
cacheOrder.finishedTasks();
}
liteOrderManager.save(cacheOrder);
liteOrderMap.put(cacheOrder.getOrderNo(), cacheOrder);
if (taskReelCount <= 0) {
//return "工单无可执行的任务";
return "order.out.noTask";
}
return "";
}
/**
* 防止仓位任务重复,需要排除掉已经分配掉的仓位
*/
public Collection<String> excludePosIds() {
//排除掉正在执行的仓位
List<DataLog> allTasks = taskService.getAllTasks();
Collection<String> operatingPosIds = new HashSet<>();
for (DataLog task : allTasks) {
String posId = task.getPosId();
if (!Strings.isNullOrEmpty(posId)) {
operatingPosIds.add(task.getPosId());
}
}
return operatingPosIds;
}
public DataLog newTask(StoragePos pos) {
DataLog task = new DataLog();
Barcode barcode = pos.getBarcode();
if (barcode != null) {
task.setPartNumber(barcode.getPartNumber());
task.setBarcode(barcode.getBarcode());
task.setNum(barcode.getAmount());
task.setMemo(barcode.getMemo());
}
Storage storage = dataCache.getStorageById(pos.getStorageId());
task.setCid(storage.getCid());
task.setStorageId(storage.getId());
task.setStorageName(storage.getName());
task.setPosId(pos.getId());
task.setPosName(pos.getPosName());
return task;
}
} }
...@@ -5,19 +5,27 @@ import com.google.common.collect.Lists; ...@@ -5,19 +5,27 @@ import com.google.common.collect.Lists;
import com.neotel.smfcore.common.annotation.QueryCondition; import com.neotel.smfcore.common.annotation.QueryCondition;
import com.neotel.smfcore.common.bean.PageData; import com.neotel.smfcore.common.bean.PageData;
import com.neotel.smfcore.common.bean.ResultBean; import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.common.csv.CsvReader;
import com.neotel.smfcore.common.exception.BadRequestException; import com.neotel.smfcore.common.exception.BadRequestException;
import com.neotel.smfcore.common.exception.ValidateException; import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.common.utils.Constants; 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.QueryHelp;
import com.neotel.smfcore.common.utils.SecurityUtils; import com.neotel.smfcore.common.utils.SecurityUtils;
import com.neotel.smfcore.core.order.LiteOrderCache; import com.neotel.smfcore.core.order.LiteOrderCache;
import com.neotel.smfcore.core.order.enums.LITEORDER_STATUS;
import com.neotel.smfcore.core.order.rest.bean.dto.OrderDto; import com.neotel.smfcore.core.order.rest.bean.dto.OrderDto;
import com.neotel.smfcore.core.order.rest.bean.mapstruct.OrderMapper; import com.neotel.smfcore.core.order.rest.bean.mapstruct.OrderMapper;
import com.neotel.smfcore.core.order.rest.bean.query.OrderQueryCondition; import com.neotel.smfcore.core.order.rest.bean.query.OrderQueryCondition;
import com.neotel.smfcore.core.order.service.manager.ILiteOrderItemManager; import com.neotel.smfcore.core.order.service.manager.ILiteOrderItemManager;
import com.neotel.smfcore.core.order.service.manager.ILiteOrderManager; import com.neotel.smfcore.core.order.service.manager.ILiteOrderManager;
import com.neotel.smfcore.core.order.service.po.LiteOrder; import com.neotel.smfcore.core.order.service.po.LiteOrder;
import com.neotel.smfcore.core.order.service.po.LiteOrderItem;
import com.neotel.smfcore.core.storage.service.po.Storage;
import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.core.system.rest.bean.mapstruct.TaskMapper; import com.neotel.smfcore.core.system.rest.bean.mapstruct.TaskMapper;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import com.neotel.smfcore.security.bean.FileProperties;
import com.neotel.smfcore.security.rest.bean.vo.UserPassVo; import com.neotel.smfcore.security.rest.bean.vo.UserPassVo;
import com.neotel.smfcore.security.service.manager.IGroupManager; import com.neotel.smfcore.security.service.manager.IGroupManager;
import com.neotel.smfcore.security.service.manager.IRoleManager; import com.neotel.smfcore.security.service.manager.IRoleManager;
...@@ -29,6 +37,7 @@ import io.swagger.annotations.Api; ...@@ -29,6 +37,7 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
...@@ -41,7 +50,11 @@ import org.springframework.validation.annotation.Validated; ...@@ -41,7 +50,11 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
...@@ -69,6 +82,8 @@ public class OrderController { ...@@ -69,6 +82,8 @@ public class OrderController {
@Autowired @Autowired
private LiteOrderCache liteOrderCache; private LiteOrderCache liteOrderCache;
@Autowired
private final FileProperties properties;
// @ApiOperation("导出用户数据") // @ApiOperation("导出用户数据")
// @GetMapping(value = "/download") // @GetMapping(value = "/download")
// @PreAuthorize("@el.check('user:list')") // @PreAuthorize("@el.check('user:list')")
...@@ -78,39 +93,75 @@ public class OrderController { ...@@ -78,39 +93,75 @@ public class OrderController {
@ApiOperation("上传工单") @ApiOperation("上传工单")
@PostMapping(value = "/upload") @PostMapping(value = "/upload")
public ResultBean updateAvatar(@RequestParam MultipartFile orderFile){ @AnonymousAccess
public ResultBean updateAvatar(@RequestParam MultipartFile orderFile) {
return null; String image = "csv";
String fileType = FileUtil.getExtensionName(orderFile.getOriginalFilename());
if (fileType != null && !image.contains(fileType)) {
throw new BadRequestException("文件格式错误!, 仅支持 " + image + " 格式");
}
File folder = new File(properties.getPath(), "pos");
File localFile = FileUtil.upload(orderFile, folder.getAbsolutePath());
List<LiteOrderItem> liteOrderItems = handleOrderCsv(localFile.getAbsolutePath());
if (liteOrderItems == null || liteOrderItems.size() <= 0) {
throw new BadRequestException("文件解析失败");
}
LiteOrder liteOrder = new LiteOrder(localFile.getName(), liteOrderItems);
liteOrder.setSource(localFile.getAbsolutePath());
liteOrder.setStatus(LITEORDER_STATUS.NEW);
LiteOrder dbOrder = liteOrderManager.findByOrderNo(liteOrder.getOrderNo());
if (dbOrder == null) {
log.info("新增加订单:" + liteOrder.getOrderNo());
liteOrder = liteOrderManager.createWithItems(liteOrder);
// TaskService.liteOrderMap.put(liteOrder.getOrderNo(), liteOrder);
} else {
log.info("数据库中已存在工单号为[" + liteOrder.getOrderNo() + "],忽略文件:" + localFile.getAbsolutePath());
throw new BadRequestException("工单号[" + liteOrder.getOrderNo() + "]已存在");
}
return ResultBean.newOkResult("工单上传成功");
} }
@ApiOperation("工单出库") @ApiOperation("工单出库")
@PostMapping(value = "/out") @PostMapping(value = "/out")
@PreAuthorize("@el.check('order:out')") @PreAuthorize("@el.check('order:out')")
public ResultBean delete(@RequestBody String orderNo) { public ResultBean delete(@RequestBody Map<String,String> mapValues) {
String orderNo = mapValues.get("orderNo");
if (orderNo == null) {
throw new BadRequestException("工单号不能为空");
}
LiteOrder liteOrder = liteOrderManager.findByOrderNo(orderNo); LiteOrder liteOrder = liteOrderManager.findByOrderNo(orderNo);
ResultBean resultBean = liteOrderCache.checkOutOrder(liteOrder); if (liteOrder == null) {
return resultBean; throw new BadRequestException("未找到工单:" + orderNo);
}
// ResultBean resultBean = liteOrderCache.checkOutOrder(liteOrder);
String result = liteOrderCache.checkOutLiteOrder(orderNo, false);
return ResultBean.newOkResult(result);
} }
@ApiOperation("查询工单") @ApiOperation("查询工单")
@GetMapping @GetMapping
@PreAuthorize("@el.check('order:list')") @PreAuthorize("@el.check('order:list')")
public PageData<OrderDto> query(OrderQueryCondition criteria, Pageable pageable){ public PageData<OrderDto> query(OrderQueryCondition criteria, Pageable pageable) {
User user = userManager.findByUserName(SecurityUtils.getCurrentUsername()); User user = userManager.findByUserName(SecurityUtils.getCurrentUsername());
if(user != null){ if (user != null) {
//数据权限 //数据权限
if(!user.getIsAdmin()){ if (!user.getIsAdmin()) {
Set<String> groupIds = user.getGroups(); Set<String> groupIds = user.getGroups();
List<String> groupNames = Lists.newArrayList(); List<String> groupNames = Lists.newArrayList();
if(!ObjectUtils.isEmpty(groupIds)){ if (!ObjectUtils.isEmpty(groupIds)) {
for (String groupId : groupIds) { for (String groupId : groupIds) {
Group group = groupManager.get(groupId); Group group = groupManager.get(groupId);
groupNames.add(group.getGroupName()); groupNames.add(group.getGroupName());
} }
} }
//都没有权限,返回空 //都没有权限,返回空
if(ObjectUtils.isEmpty(groupNames)){ if (ObjectUtils.isEmpty(groupNames)) {
return new PageData<>(Lists.newArrayList(),0); return new PageData<>(Lists.newArrayList(), 0);
} }
criteria.setSourceList(groupNames); criteria.setSourceList(groupNames);
} }
...@@ -118,4 +169,66 @@ public class OrderController { ...@@ -118,4 +169,66 @@ public class OrderController {
PageData<LiteOrder> orderList = liteOrderManager.findByPage(QueryHelp.getQuery(criteria), pageable); PageData<LiteOrder> orderList = liteOrderManager.findByPage(QueryHelp.getQuery(criteria), pageable);
return orderMapper.toDto(orderList); return orderMapper.toDto(orderList);
} }
private int getCsvIndex(CsvReader csvReader, String titleName, String titleNameEn) {
int index = csvReader.getIndex(titleName, titleNameEn);
if (index == -1) {
log.info("未包含【" + titleName + "】或【" + titleNameEn + "】列");
throw new ValidateException("必须包含[" + titleNameEn + "]列");
}
return index;
}
protected List<LiteOrderItem> handleOrderCsv(String fileURL) {
try {
log.info("开始更解析上传的工单");
List<LiteOrderItem> items = Lists.newArrayList();
CsvReader csvRead = new CsvReader(fileURL);
csvRead.setSkipEmptyRecords(true);//忽略空行
csvRead.setTrimWhitespace(true);//去除空格
csvRead.readHeaders();
int partNumberIndex = csvRead.getIndex("PN", "PN");
int qtyIndex = csvRead.getIndex("NUM", "QTY");
int feederIndex = csvRead.getIndex("FEEDER", "FEEDER");
int row = 1;
int newRowCount = 0;
int updateRowCount = 0;
while (csvRead.readRecord()) {
row++;
String[] lineValues = csvRead.getValues();
String partNumber = lineValues[partNumberIndex];
if (partNumber.isEmpty()) {
log.warn("行[partNumber=" + partNumber + "]中PN 为空,此行忽略");
} else {
int num = 1;
if (qtyIndex != -1) {
String numStr = lineValues[qtyIndex];
if (Strings.isNotBlank(numStr)) {
try {
num = Integer.valueOf(numStr);
} catch (Exception e) {
log.error(partNumber + "的数量:" + numStr + " 不是数字,使用1");
}
}
}
String feeder = "";
if (feederIndex != -1) {
feeder = lineValues[feederIndex];
}
LiteOrderItem item = new LiteOrderItem();
item.setPn(partNumber);
item.setNeedNum(num);
item.setFeederInfo(feeder);
items.add(item);
}
}
return items;
} catch (Exception ex) {
log.error("解析上传的工单出错:" + ex.toString());
}
return null;
}
} }
package com.neotel.smfcore.core.order.rest.bean.dto; package com.neotel.smfcore.core.order.rest.bean.dto;
import com.neotel.smfcore.core.order.enums.LITEORDER_STATUS; import com.neotel.smfcore.core.order.enums.LITEORDER_STATUS;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.springframework.data.annotation.Transient; import org.springframework.data.annotation.Transient;
...@@ -11,44 +12,61 @@ import java.util.List; ...@@ -11,44 +12,61 @@ import java.util.List;
@Getter @Getter
@Setter @Setter
public class OrderDto implements Serializable { public class OrderDto implements Serializable {
@ApiModelProperty(value = "ID")
private String id;
/** /**
* 订单号 * 订单号
*/ */
@ApiModelProperty("工单号")
private String orderNo; private String orderNo;
/** /**
* 当前任务盘数 * 当前任务盘数
*/ */
@ApiModelProperty("当前任务盘数")
private int taskReelCount = 0; private int taskReelCount = 0;
/** /**
* 当前任务已完成盘数 * 当前任务已完成盘数
*/ */
@ApiModelProperty("当前任务已完成盘数")
private int finishedReelCount = 0; private int finishedReelCount = 0;
/** /**
* 订单状态 * 订单状态
* 0=新建工单
* 1=首套料正在执行
* 2=首盘料已结束,等待出尾料
* 3=正在出尾料
* 4=尾料已完成
* 5=正在补料
* 6=补料已完成
*/ */
@ApiModelProperty("订单状态")
private int status = LITEORDER_STATUS.NEW; private int status = LITEORDER_STATUS.NEW;
/** /**
* 出库状态, 2表示已完成 * 出库状态, 2表示已完成
*/ */
@ApiModelProperty("出库状态, 2表示已完成")
private boolean closed = false; private boolean closed = false;
/** /**
* 工单来源 * 工单来源
*/ */
@ApiModelProperty("工单来源")
private String source = ""; private String source = "";
/** /**
* 任务完成时间(用于关闭页面显示) * 任务完成时间(用于关闭页面显示)
*/ */
@ApiModelProperty("任务完成时间(用于关闭页面显示)")
@Transient @Transient
private long taskFinishedTime = -1; private long taskFinishedTime = -1;
/** /**
* 套(倍)数 * 套(倍)数
*/ */
@ApiModelProperty("套(倍)数")
private float orderTimes = 1f; private float orderTimes = 1f;
} }
...@@ -31,7 +31,13 @@ public class LiteOrderManagerImpl implements ILiteOrderManager { ...@@ -31,7 +31,13 @@ public class LiteOrderManagerImpl implements ILiteOrderManager {
@Override @Override
public LiteOrder findByOrderNo(String orderNo) { public LiteOrder findByOrderNo(String orderNo) {
return liteOrderDao.findOneByCondition(new String[] {"orderNo"}, new String[] {orderNo}); LiteOrder order= liteOrderDao.findOneByCondition(new String[] {"orderNo"}, new String[] {orderNo});
if(order!=null&& order.getOrderItems()==null){
List<LiteOrderItem> items=liteOrderItemManager.findOrderItems(orderNo);
order.setOrderItems(items);
}
return order;
} }
@Override @Override
......
...@@ -205,9 +205,16 @@ public class StorageController { ...@@ -205,9 +205,16 @@ public class StorageController {
return ResultBean.newOkResult(resultMsg); return ResultBean.newOkResult(resultMsg);
} }
/**
* private int getCsvIndex(CsvReader csvReader, String titleName, String titleNameEn) {
*/ int index = csvReader.getIndex(titleName, titleNameEn);
if (index == -1) {
log.info("未包含【" + titleName + "】或【" + titleNameEn + "】列");
throw new ValidateException("必须包含[" + titleNameEn + "]列");
}
return index;
}
protected String handleStoragePos(String fileURL, String storageId) throws Exception protected String handleStoragePos(String fileURL, String storageId) throws Exception
{ {
log.info("开始更新料仓【"+storageId+"】的位置信息"); log.info("开始更新料仓【"+storageId+"】的位置信息");
...@@ -220,30 +227,15 @@ public class StorageController { ...@@ -220,30 +227,15 @@ public class StorageController {
log.error("Storage id is not exist"); log.error("Storage id is not exist");
throw new ValidateException("storage.error.notExist"); throw new ValidateException("storage.error.notExist");
} }
CsvReader csvRead = new CsvReader(fileURL); CsvReader csvRead = new CsvReader(fileURL);
csvRead.setSkipEmptyRecords(true);//忽略空行 csvRead.setSkipEmptyRecords(true);//忽略空行
csvRead.setTrimWhitespace(true);//去除空格 csvRead.setTrimWhitespace(true);//去除空格
csvRead.readHeaders(); csvRead.readHeaders();
int posIndex = csvRead.getIndex("位置","pos"); int posIndex =getCsvIndex(csvRead, "位置","pos");
if(posIndex == -1){ int priIndex = getCsvIndex(csvRead,"优先级","pri");
log.info("未包含【位置】或【pos】列"); int hIndex = getCsvIndex(csvRead,"高度","h");
throw new ValidateException("必须包含[位置]列"); int wIndex = getCsvIndex(csvRead,"宽度","w");
}
int priIndex = csvRead.getIndex("优先级","pri");
if (priIndex == -1){
log.info("未包含【优先级】或【pri】列");
throw new ValidateException("必须包含[优先级]列");
}
int hIndex = csvRead.getIndex("高度","h");
if (hIndex == -1){
log.info("未包含【高度】或【h】列");
throw new ValidateException("必须包含【高度】列");
}
int wIndex = csvRead.getIndex("宽度","w");
if (wIndex == -1){
log.info("未包含【宽度】或【w】列");
throw new ValidateException("必须包含【宽度】列");
}
int row = 1; int row = 1;
int newRowCount = 0; int newRowCount = 0;
...@@ -263,6 +255,7 @@ public class StorageController { ...@@ -263,6 +255,7 @@ public class StorageController {
if(posInfo == null){ if(posInfo == null){
posInfo = new StoragePos(); posInfo = new StoragePos();
posInfo.setPosName(posName); posInfo.setPosName(posName);
posInfo.setStorageId(storageId);
newRowCount++; newRowCount++;
}else{ }else{
updateRowCount++; updateRowCount++;
......
package com.neotel.smfcore.core.storage.rest; package com.neotel.smfcore.core.storage.rest;
import com.google.common.base.Strings;
import com.neotel.smfcore.common.bean.PageData; import com.neotel.smfcore.common.bean.PageData;
import com.neotel.smfcore.common.exception.BadRequestException; import com.neotel.smfcore.common.exception.BadRequestException;
import com.neotel.smfcore.common.utils.Constants;
import com.neotel.smfcore.common.utils.QueryHelp; import com.neotel.smfcore.common.utils.QueryHelp;
import com.neotel.smfcore.common.utils.StorageConstants;
import com.neotel.smfcore.core.barcode.enums.COMPONENT_TYPE;
import com.neotel.smfcore.core.device.util.DataCache; import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.storage.rest.dto.CheckOutDto;
import com.neotel.smfcore.core.storage.rest.dto.StoragePosDto; import com.neotel.smfcore.core.storage.rest.dto.StoragePosDto;
import com.neotel.smfcore.core.storage.rest.dto.StoragePosEnabledDto; import com.neotel.smfcore.core.storage.rest.dto.StoragePosEnabledDto;
import com.neotel.smfcore.core.storage.rest.dto.StoragePosSaveDto; import com.neotel.smfcore.core.storage.rest.dto.StoragePosSaveDto;
import com.neotel.smfcore.core.storage.rest.mapstruct.StoragePosMapper; import com.neotel.smfcore.core.storage.rest.mapstruct.StoragePosMapper;
import com.neotel.smfcore.core.storage.rest.query.StoragePosFindCriteria;
import com.neotel.smfcore.core.storage.rest.query.StoragePosQueryCriteria; import com.neotel.smfcore.core.storage.rest.query.StoragePosQueryCriteria;
import com.neotel.smfcore.core.storage.service.dao.IStoragePosDao; import com.neotel.smfcore.core.storage.service.dao.IStoragePosDao;
import com.neotel.smfcore.core.storage.service.manager.IStoragePosManager; import com.neotel.smfcore.core.storage.service.manager.IStoragePosManager;
import com.neotel.smfcore.core.storage.service.po.Storage; import com.neotel.smfcore.core.storage.service.po.Storage;
import com.neotel.smfcore.core.storage.service.po.StoragePos; import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.core.system.util.TaskService;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
...@@ -20,6 +28,7 @@ import lombok.RequiredArgsConstructor; ...@@ -20,6 +28,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable; 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.data.mongodb.core.query.Query;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
...@@ -27,9 +36,9 @@ import org.springframework.security.access.prepost.PreAuthorize; ...@@ -27,9 +36,9 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.ArrayList; import javax.servlet.http.HttpServletRequest;
import java.util.List; import java.util.*;
import java.util.Set; import java.util.regex.Pattern;
@Slf4j @Slf4j
@RestController @RestController
...@@ -46,6 +55,9 @@ public class StoragePosController { ...@@ -46,6 +55,9 @@ public class StoragePosController {
private final StoragePosMapper storagePosMapper; private final StoragePosMapper storagePosMapper;
@Autowired @Autowired
private DataCache dataCache; private DataCache dataCache;
@Autowired
private TaskService taskService;
@ApiOperation("查询库位") @ApiOperation("查询库位")
...@@ -144,4 +156,71 @@ public class StoragePosController { ...@@ -144,4 +156,71 @@ public class StoragePosController {
storagePosManager.deletePoss(ids); storagePosManager.deletePoss(ids);
return new ResponseEntity<>(HttpStatus.OK); return new ResponseEntity<>(HttpStatus.OK);
} }
@ApiOperation("查找出库列表")
@GetMapping("/find")
@PreAuthorize("@el.check('storage:list')")
public PageData<StoragePosDto> storagePosFind(StoragePosFindCriteria criteria, Pageable pageable,HttpServletRequest request){
Query query= QueryHelp.getQuery(criteria);
Criteria baseCriteria= Criteria.where("used").is(true);
int componentType = criteria.getType();
String name="";
if(componentType != -1){
int type = componentType;
request.setAttribute("type", componentType);
if(componentType == 41){//锡膏夹具
type = COMPONENT_TYPE.FIXTURE;
name = StorageConstants.PACKAGE_TYPE.SOLDER_FIXTURE.getCode();
}else if(componentType == 42){//PCB夹具
type = COMPONENT_TYPE.FIXTURE;
name = StorageConstants.PACKAGE_TYPE.PCB_FIXTURE.getCode();
}
baseCriteria.and("barcode.type").is(type);
}
String expire = criteria.getExpire();
if(!Strings.isNullOrEmpty(expire)){
if("solder".equalsIgnoreCase(expire)){
baseCriteria.and("barcode.expTime").lte(new Date());
}else if("pcb".equalsIgnoreCase(expire)){
baseCriteria.and("barcode.expireDate").lte(new Date());
}
request.setAttribute("expire",expire);
}
query.addCriteria(baseCriteria);
PageData<StoragePos> pages=storagePosManager.findByPage(query,pageable);
List<StoragePosDto> StoragePosDtos=storagePosMapper.toDto(pages.getContent());
return new PageData(StoragePosDtos,pages.getTotalElements());
}
@ApiOperation("查找出库")
@PutMapping("/checkout")
public ResponseEntity<Object> checkout(@Validated @RequestBody CheckOutDto checkOutDto) {
String isSingleOutStr = checkOutDto.getSingleOut();
boolean isSingleOut = Boolean.valueOf(isSingleOutStr);
String pids = checkOutDto.getPids();
for (String pid : pids.split(";")) {
StoragePos pos = storagePosManager.get(pid);
if (pos == null) {
throw new BadRequestException("位置[" + pid + "]不存在");
}
Storage storage = dataCache.getStorageById(pos.getStorageId());
if (storage == null) {
throw new BadRequestException("料仓[" + pos.getStorageId() + "]不存在");
}
log.info("出库料仓【" + storage.getName() + "_" + storage.getCid() + "】位置仓位【" + pos.getPosName() + "】");
String outResult = taskService.checkout(storage, pos, isSingleOut);
if (!Strings.isNullOrEmpty(outResult)) {
throw new BadRequestException(outResult);
}
}
return new ResponseEntity<>(HttpStatus.OK);
}
} }
package com.neotel.smfcore.core.storage.rest.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class CheckOutDto {
@ApiModelProperty("库位号,多个用;分隔")
private String pids;
@ApiModelProperty("是否是单盘出库")
private String singleOut;
}
package com.neotel.smfcore.core.storage.rest.dto; package com.neotel.smfcore.core.storage.rest.dto;
import com.neotel.smfcore.core.barcode.rest.bean.dto.BarcodeDto;
import com.neotel.smfcore.core.barcode.service.po.Barcode; import com.neotel.smfcore.core.barcode.service.po.Barcode;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Getter; import lombok.Getter;
...@@ -18,7 +19,7 @@ public class StoragePosDto implements Serializable { ...@@ -18,7 +19,7 @@ public class StoragePosDto implements Serializable {
private String storageId; private String storageId;
@ApiModelProperty("条码") @ApiModelProperty("条码")
private Barcode barcode; private BarcodeDto barcode;
@ApiModelProperty("库位号") @ApiModelProperty("库位号")
private String posName; private String posName;
......
package com.neotel.smfcore.core.storage.rest.query;
import com.neotel.smfcore.common.annotation.QueryCondition;
import com.neotel.smfcore.common.bean.BetweenData;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
public class StoragePosFindCriteria {
@QueryCondition(blurry = "barcode,posName")
private String blurry;
@QueryCondition(type = QueryCondition.Type.BETWEEN, propName = "updateDate")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private BetweenData<Date> createDate;
@QueryCondition
@ApiModelProperty("料仓ID")
private String storageId;
@QueryCondition(propName = "barcode.barcode")
@ApiModelProperty("条码")
private String barcode;
@QueryCondition
@ApiModelProperty("库位号")
private String posName;
@ApiModelProperty("类型")
private int type =-1 ;
@ApiModelProperty("是否过期")
private String expire;
@QueryCondition(blurry = "barcode.providerNumber" )
private String providerNumber;
@QueryCondition(blurry = "barcode.partNumber")
private String partNumber;
@QueryCondition(blurry = "barcode.memo")
private String memo;
@QueryCondition(propName = "barcode.lockId")
private String lockId;
@QueryCondition(blurry = "barcode.batch")
private String batch;
@QueryCondition(blurry = "barcode.provider")
private String provider;
@QueryCondition(blurry = "barcode.otherField1")
private String otherField1;
@QueryCondition(blurry = "barcode.otherField2")
private String otherField2;
@QueryCondition(blurry = "barcode.otherField3")
private String otherField3;
@QueryCondition(blurry = "barcode.otherField4")
private String otherField4;
@QueryCondition(blurry = "barcode.otherField5")
private String otherField5;
}
...@@ -15,11 +15,10 @@ ...@@ -15,11 +15,10 @@
*/ */
package com.neotel.smfcore.security.rest; package com.neotel.smfcore.security.rest;
import com.neotel.smfcore.common.utils.*;
import com.neotel.smfcore.security.annotation.AnonymousDeleteMapping; import com.neotel.smfcore.security.annotation.AnonymousDeleteMapping;
import com.neotel.smfcore.security.annotation.AnonymousGetMapping; import com.neotel.smfcore.security.annotation.AnonymousGetMapping;
import com.neotel.smfcore.security.annotation.AnonymousPostMapping; import com.neotel.smfcore.security.annotation.AnonymousPostMapping;
import com.neotel.smfcore.common.utils.EncryptUtils;
import com.neotel.smfcore.common.utils.StringUtils;
import com.neotel.smfcore.security.bean.RsaProperties; import com.neotel.smfcore.security.bean.RsaProperties;
import com.neotel.smfcore.security.TokenProvider; import com.neotel.smfcore.security.TokenProvider;
import com.neotel.smfcore.security.bean.LoginProperties; import com.neotel.smfcore.security.bean.LoginProperties;
...@@ -28,8 +27,6 @@ import com.neotel.smfcore.security.rest.bean.dto.OnlineUserDto; ...@@ -28,8 +27,6 @@ import com.neotel.smfcore.security.rest.bean.dto.OnlineUserDto;
import com.neotel.smfcore.security.service.OnlineUserService; import com.neotel.smfcore.security.service.OnlineUserService;
import com.neotel.smfcore.security.rest.bean.dto.AuthUserDto; import com.neotel.smfcore.security.rest.bean.dto.AuthUserDto;
import com.neotel.smfcore.security.rest.bean.dto.JwtUserDto; import com.neotel.smfcore.security.rest.bean.dto.JwtUserDto;
import com.neotel.smfcore.common.utils.RsaUtils;
import com.neotel.smfcore.common.utils.SecurityUtils;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
...@@ -103,7 +100,8 @@ public class AuthorizationController { ...@@ -103,7 +100,8 @@ public class AuthorizationController {
OnlineUserDto onlineUserDto = null; OnlineUserDto onlineUserDto = null;
try { try {
long seconds = onlineUserService.properties.getTokenValidityInSeconds() / 1000; long seconds = onlineUserService.properties.getTokenValidityInSeconds() / 1000;
onlineUserDto = new OnlineUserDto(jwtUserDto.getUsername(), browser , ip, address, EncryptUtils.desEncrypt(token), new Date()); Date exTime= DateUtil.addSeconds(new Date(), new Long(seconds).intValue());
onlineUserDto = new OnlineUserDto(jwtUserDto.getUsername(), browser , ip, address, EncryptUtils.desEncrypt(token), new Date(),exTime);
} catch (Exception e) { } catch (Exception e) {
log.error(e.getMessage(),e); log.error(e.getMessage(),e);
} }
......
...@@ -59,6 +59,10 @@ public class OnlineUserDto { ...@@ -59,6 +59,10 @@ public class OnlineUserDto {
* 登录时间 * 登录时间
*/ */
private Date loginTime; private Date loginTime;
/**
* 过期时间
*/
private Date expiresTime;
} }
...@@ -23,6 +23,8 @@ import com.neotel.smfcore.security.rest.bean.dto.OnlineUserDto; ...@@ -23,6 +23,8 @@ import com.neotel.smfcore.security.rest.bean.dto.OnlineUserDto;
import com.neotel.smfcore.common.utils.EncryptUtils; import com.neotel.smfcore.common.utils.EncryptUtils;
import com.neotel.smfcore.common.utils.FileUtil; import com.neotel.smfcore.common.utils.FileUtil;
import com.neotel.smfcore.common.utils.StringUtils; import com.neotel.smfcore.common.utils.StringUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
...@@ -128,7 +130,26 @@ public class OnlineUserService { ...@@ -128,7 +130,26 @@ public class OnlineUserService {
* @return / * @return /
*/ */
public OnlineUserDto getOne(String key) { public OnlineUserDto getOne(String key) {
return (OnlineUserDto)onlineUserMap.get(key); OnlineUserDto dto = null;
dto = (OnlineUserDto) onlineUserMap.get(key);
if(dto==null) {
//已过期抛异常
throw new ExpiredJwtException(null, null, "token 已过期, 未找到用户信息");
}
Date currTime = new Date();
int result = dto.getExpiresTime().compareTo(new Date());
if (result > 0) {
//更新过期时间
long seconds = properties.getTokenValidityInSeconds() / 1000;
Date exTime = DateUtil.addSeconds(new Date(), new Long(seconds).intValue());
dto.setExpiresTime(exTime);
} else if (result < 0) {
this.kickOut(key);
//已过期抛异常
throw new ExpiredJwtException(null, null, "token 已过期,过期时间:"+dto.getExpiresTime());
}
return dto;
} }
/** /**
......
...@@ -17,6 +17,8 @@ package com.neotel.smfcore.security.service; ...@@ -17,6 +17,8 @@ package com.neotel.smfcore.security.service;
import com.neotel.smfcore.common.exception.BadRequestException; import com.neotel.smfcore.common.exception.BadRequestException;
import com.neotel.smfcore.common.exception.EntityNotFoundException; import com.neotel.smfcore.common.exception.EntityNotFoundException;
import com.neotel.smfcore.common.utils.Constants;
import com.neotel.smfcore.common.utils.Md5Utls;
import com.neotel.smfcore.security.bean.LoginProperties; import com.neotel.smfcore.security.bean.LoginProperties;
import com.neotel.smfcore.security.rest.bean.dto.JwtUserDto; import com.neotel.smfcore.security.rest.bean.dto.JwtUserDto;
import com.neotel.smfcore.security.service.manager.IMenuManager; import com.neotel.smfcore.security.service.manager.IMenuManager;
...@@ -85,6 +87,15 @@ public class UserDetailsServiceImpl implements UserDetailsService { ...@@ -85,6 +87,15 @@ public class UserDetailsServiceImpl implements UserDetailsService {
if (!user.getEnabled()) { if (!user.getEnabled()) {
throw new BadRequestException("账号未激活!"); throw new BadRequestException("账号未激活!");
} }
if(user.getUsername().equals(Constants.SUPER_USERNAME)){
}else {
//判断激活码是否正确
String code = Md5Utls.getMd5(user.getId(), user.getCreateDate());
if (!code.equals(user.getCheckCode())) {
throw new BadRequestException("账号未激活!");
}
}
List<Long> dataScopes = new ArrayList<>(); List<Long> dataScopes = new ArrayList<>();
jwtUserDto = new JwtUserDto( jwtUserDto = new JwtUserDto(
user, user,
......
...@@ -36,8 +36,8 @@ jwt: ...@@ -36,8 +36,8 @@ jwt:
token-start-with: Bearer token-start-with: Bearer
# 必须使用最少88位的Base64对该令牌进行编码 # 必须使用最少88位的Base64对该令牌进行编码
base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI= base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI=
# 令牌过期时间 此处单位/毫秒 ,默认4小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html # 令牌过期时间 此处单位/毫秒 ,默认30分钟,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html
token-validity-in-seconds: 14400000 token-validity-in-seconds: 1800000
# 在线用户key # 在线用户key
online-key: online-token- online-key: online-token-
# 验证码 # 验证码
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!