Commit c80451cc sunke

成本中心领料-大于等于需求量最小的料盘数量

线边仓间转储出库,转外协出库,发运单出库-整盘优先原则,不足发散盘
已使用库位加入缓存
产线补料出库BUG修正
1 个父辈 ad6cd77e
......@@ -45,7 +45,7 @@ public class DataInitManager {
MainTimer mainTimer;
//@Value("${menu.show}")
private String[] menuShowList = new String[]{"productionLineReple","productionLineOut"};
private String[] menuShowList = new String[]{"productionLineReple","productionLineOut","interfaceException"};
//@Value("${menu.hide}")
private String[] menuHideList = new String[]{};
......
......@@ -270,6 +270,10 @@ public class DataCache {
*/
private static Map<String,Map<String,InventoryItem>> inventoryMap = new ConcurrentHashMap<>();
/**
* 库位占用Map, key为cid,value为已使用的库位列表
*/
private static Map<String,List<String>> usedPosNameMap = new ConcurrentHashMap<>();
/**
......@@ -518,6 +522,44 @@ public class DataCache {
}
/**
* 出库时清除使用库位列表
*/
private void removeUsedPosNameList(String cid, String posName){
List<String> usedPosNameList = getUsedPosNameList(cid);
usedPosNameList.remove(posName);
usedPosNameMap.put(cid, usedPosNameList);
}
/**
* 入库时增加使用库位列表
*/
private void addUsedPosNameList(String cid, String posName){
List<String> usedPosNameList = getUsedPosNameList(cid);
usedPosNameList.add(posName);
usedPosNameMap.put(cid, usedPosNameList);
}
/**
* 获取设备所有占用的库位名称列表
*/
public List<String> getUsedPosNameList(String cid){
List<String> posNameList = usedPosNameMap.get(cid);
if(posNameList == null){
Storage storage = getStorage(cid);
posNameList = new ArrayList<>();
if(storage != null){
log.info("加载["+cid+"]所有已使用库位到缓存");
List<StoragePos> allPos = storagePosManager.findNotEmptyByStorageId(storage.getId());
for (StoragePos pos : allPos) {
posNameList.add(pos.getPosName());
}
usedPosNameMap.put(cid,posNameList);
}
}
return posNameList;
}
public InventoryItem getStorageInventoryByPartNumber(String cid, String partNumber){
Map<String, InventoryItem> storageInventory = getStorageInventory(cid);
InventoryItem partNumberInventoryItem = storageInventory.get(partNumber);
......@@ -558,7 +600,7 @@ public class DataCache {
* @param amount
* @return
*/
public int updateInventoryAmount(String cid,String partNumber,int amount){
private int updateInventoryAmount(String cid,String partNumber,int amount){
if(amount != 0){
InventoryItem inventoryItem = getStorageInventoryByPartNumber(cid,partNumber);
if(inventoryItem == null){
......@@ -586,11 +628,12 @@ public class DataCache {
//出库
amount = - barcode.getAmount();
storage.emptyOnePos(pos);
removeUsedPosNameList(cid, pos.getPosName());
}else{
//入库
amount = barcode.getAmount();
storage.useOnePos(pos);
addUsedPosNameList(cid, pos.getPosName());
//入库单处理
if(ObjectUtil.isNotEmpty(storage.getInListName())){
inListCache.UpdateInList(storage.getInListName(),pos,barcode);
......
......@@ -42,8 +42,7 @@ public class LanguageMsgService {
int hasCount=1;
Map<String,Map<String, LanguageMsg>> resourceMap=new HashMap<>();
List<LanguageMsg> msgs = languageMsgManager.findByQuery(new Query());
for (LanguageMsg msg :
msgs) {
for (LanguageMsg msg : msgs) {
if(msg.getCode().startsWith("smfcode.")||msg.getType().equals("smfcode")){
String newCode=msg.getCode().replace("smfcode.","smfcore.");
msg.setCode(newCode);
......@@ -235,10 +234,8 @@ public class LanguageMsgService {
List<LanguageMsg> newLanguageList = new ArrayList<>();
List<LanguageMsg> updateLanguageList = new ArrayList<>();
if (proMap != null && proMap.size() > 0) {
for (String key :
proMap.keySet()) {
for (String key : proMap.keySet()) {
//如果Key爲空,直接返回
if(ObjectUtil.isEmpty(key))
{
......@@ -273,8 +270,7 @@ public class LanguageMsgService {
if (newLanguageList.size() > 0) {
languageMsgManager.insertAll(newLanguageList);
for (LanguageMsg msg :
newLanguageList) {
for (LanguageMsg msg : newLanguageList) {
MessageUtils.updateMsg(msg);
}
}
......
......@@ -283,6 +283,15 @@ public class LiteOrderCache implements ITaskListener {
newItems = (ArrayList<HikOrderInfo>) apiResult.getData();
}
}
// newItems = Lists.newArrayList();
// HikOrderInfo item = new HikOrderInfo();
// item.setBaseCode("BaseCode");
// item.setQty(1000);
// item.setMaterialNo("100100704");
// item.setStation("AAA");
// item.setJobNo("1001583501_1");
// item.setReplenishmentNo("8001B22070600061");
// newItems.add(item);
if (newItems != null) {
//删除旧的Items
......@@ -439,13 +448,12 @@ public class LiteOrderCache implements ITaskListener {
boolean needJieliao =false;
//查找PN的所有库存,PN=pn,未锁定,qty 从大到小,入库时间正序
//查找PN的所有库存,PN=pn,未锁定,qty 从大到小,批次正序, 入库时间正序
List<StoragePos> posList = storagePosManager.findOrderItemInStorage(availableStorageIds, pn, excludePosIds);
int storageNum=0;
int reelNum=posList.size();
for (StoragePos pos :posList
) {
for (StoragePos pos :posList) {
storageNum+=pos.getBarcode().getAmount();
}
......@@ -455,9 +463,9 @@ public class LiteOrderCache implements ITaskListener {
log.info("工单[" + cacheOrder.getOrderNo() + "]缺料出库: 物料号[" + pn + "] ,需求数量[" + orderItem.getWemng() + "], 未找到元器件信息 ");
shortage = true;
//判断库存 使用最小库存盘数:当前盘数<=最小库存盘数时,需要截料
if(component.getMinStoreNum()>0&& reelNum<=component.getMinStoreNum()){
needJieliao=true;
}
// if(component.getMinStoreNum()>0&& reelNum<=component.getMinStoreNum()){
// needJieliao=true;
// }
}else {
log.info("工单[" + cacheOrder.getOrderNo() + "] 物料号[" + pn + "] ,需求数量[" + orderItem.getWemng() + "], 未找到元器件信息, 缺料 ");
return materialShortPro(userName, cacheOrder);
......@@ -488,15 +496,18 @@ public class LiteOrderCache implements ITaskListener {
}
}
//判断库存 使用最小库存盘数:当前盘数<=最小库存盘数时,需要截料
if(component.getMinStoreNum()>0&& reelNum<=component.getMinStoreNum()){
needJieliao=true;
}
List<StoragePos> itemPosList = new ArrayList<>();
List<String> itemPosNameList = new ArrayList<>();
//此PN未完成
int targetNum = needNum;
for (int i=0;i<posList.size();i++
) {
for (int i=0;i<posList.size();i++) {
List<StoragePos> forPosList=new ArrayList<>();
for (StoragePos pos :
posList) {
for (StoragePos pos : posList) {
if(!itemPosNameList.contains(pos.getPosName())){
forPosList.add(pos);
}
......@@ -504,8 +515,7 @@ public class LiteOrderCache implements ITaskListener {
//循环剩余的库位,查找
int forIndex=-1;
for (StoragePos pos :
forPosList) {
for (StoragePos pos : forPosList) {
forIndex++;
boolean isLast=(forIndex==(forPosList.size()-1));
//已经在出库列表
......@@ -621,6 +631,9 @@ public class LiteOrderCache implements ITaskListener {
int itemReelCount=0;
int itemOutCount=0;
List<StoragePos> posList=needOutPosMap.get(orderItem.getMaterialNo());
if(posList == null){
posList = new ArrayList<>();
}
for (StoragePos pos : posList) {
DataLog task = taskService.newTask(pos) ;
......@@ -650,7 +663,12 @@ public class LiteOrderCache implements ITaskListener {
if(addOutbound){
task.setInOperate(true);
task.setAddOutbound(true);
task.setLightColor(ORDER_COLOR.PINK.getRgb());//补料出库 颜色:PINK
task.setLightColor(ORDER_COLOR.PINK.getRgb());//缺料出库 颜色:PINK
}
if(cacheOrder.isRepleOrder()){
//产线补料
task.setLightColor(ORDER_COLOR.FORESTGREEN.getRgb());//产线补料出库 颜色:FORESTGREEN
}
try{
taskService.addTaskToExecute(task);
......
......@@ -29,6 +29,10 @@ public enum ORDER_COLOR {
// 'white':[15,125,125,125],
// 'off':[16,0,0,0],
// 'magenta':[17,125,125,0]
//手动出库:BLUE;入库:DARKGREEN;
// 工单首盘料:CYAN;工单截料:PURPLE;工单备件:SKYBLUE;
// 工单缺料出库:PINK;普通转储出库单:FIREBRICK;产线实料出库 颜色:FORESTGREEN
BLUE("0000FF"),
//MAGENTA("FF00FF"),
CYAN("00FFFF"),
......@@ -37,8 +41,8 @@ public enum ORDER_COLOR {
SKYBLUE("6CA6CD"),
PINK("FF1493"),
FORESTGREEN("228B22"),
LIGHTBLUE("8470FF"),
INDIANRED("8B3A3A"),
LIGHTBLUE("8470FF"),//暂时未使用
INDIANRED("8B3A3A"),//暂时未使用
DARKGREEN("556B2F"),
;
......
......@@ -212,7 +212,7 @@ public class RepleOrderController {
@ApiOperation("料盘出库界面,获取执行的工单列表")
@GetMapping("/executeOrders")
@PreAuthorize("@el.check('reelOut')")
@PreAuthorize("@el.check('productionLineReple')")
public List<OrderDto> queryExecuteOrder() {
//查询正在执行的工单列表
Query query = new Query(Criteria.where("status").is(LITEORDER_STATUS.EXECUTING).and("replenishmentNo").ne(null));
......@@ -252,7 +252,7 @@ public class RepleOrderController {
@ApiOperation("料盘出库界面,获取当前产线补料任务列表")
@GetMapping("/reelOutTasks")
@PreAuthorize("@el.check('reelOut')")
@PreAuthorize("@el.check('productionLineReple')")
public List<TaskDto> queryReelOutTasks(@RequestParam Map<String, String> paramsMap) {
//查询正在执行的工单列表
......@@ -276,7 +276,7 @@ public class RepleOrderController {
@ApiOperation("料盘出库界面,切换到下一个工单")
@PostMapping("/nextOrder")
@PreAuthorize("@el.check('reelOut')")
@PreAuthorize("@el.check('productionLineReple')")
public ResultBean nextOrder(@RequestParam Map<String, String> paramsMap) {
if (ObjectUtil.isNotEmpty(currOrderNo)) {
......@@ -295,6 +295,7 @@ public class RepleOrderController {
}
LiteOrder liteOrder = orderList.get(0);
currOrderNo = liteOrder.getOrderNo();
//设置此工单的任务可以发送给料架
List<DataLog> taskList = getOrderTaskByUser(liteOrder, true);
for (DataLog datalog : taskList) {
......@@ -306,7 +307,7 @@ public class RepleOrderController {
}
@ApiOperation("齐套页面,获取齐套数据")
@GetMapping("/orderSet")
@PreAuthorize("@el.check('workOrder')")
@PreAuthorize("@el.check('productionLineReple')")
public List<OrderPnDto> orderSetData( ) {
List<OrderPnInfo> orderPnInfos=orderPnCache.getDataList();
......@@ -315,7 +316,7 @@ public class RepleOrderController {
}
@ApiOperation("齐套页面,刷新齐套数据")
@PostMapping("/orderSet/update")
@PreAuthorize("@el.check('workOrder')")
@PreAuthorize("@el.check('productionLineReple')")
public ResultBean updateOrderSet(HttpServletRequest request ) {
boolean result = orderPnCache.reloadData();
if (!result) {
......@@ -328,7 +329,7 @@ public class RepleOrderController {
@ApiOperation("导出齐套列表")
@GetMapping(value = "/orderSet/download")
@PreAuthorize("@el.check('workOrder')")
@PreAuthorize("@el.check('productionLineReple')")
public void download(HttpServletResponse response, HttpServletRequest request) throws IOException {
List<OrderPnInfo> orderPnInfos=orderPnCache.getDataList();
download(orderPnInfos,response,request.getLocale());
......@@ -353,7 +354,7 @@ public class RepleOrderController {
private List<LiteOrder> getExecuteOrders() {
//查询正在执行的工单列表
Query query = new Query(Criteria.where("status").is(LITEORDER_STATUS.EXECUTING).and("replenishmentNo").not());
Query query = new Query(Criteria.where("status").is(LITEORDER_STATUS.EXECUTING).and("replenishmentNo").ne(null));
//根据开始出库时间排序
Sort sort = Sort.by(Sort.Direction.ASC, "startOutTime");
query.with(sort);
......
......@@ -8,6 +8,7 @@ import com.neotel.smfcore.core.order.enums.LITEORDER_STATUS;
import com.neotel.smfcore.hikvision.bean.HikOrderInfo;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;
......@@ -260,6 +261,15 @@ public class LiteOrder extends BasePo implements Serializable {
return status == LITEORDER_STATUS.ADDOUTBOUND;
}
/**
* 是否是产线补(有补料单号)
* @return
*/
public boolean isRepleOrder(){
//是否是产线补料
return Strings.isNotBlank(replenishmentNo);
}
public void setTaskReelCount(int taskReelCount) {
......
......@@ -270,23 +270,16 @@ public class OutListCache implements ITaskListener {
}
}
List<StoragePos> itemPosList = new ArrayList<>();
//此PN未完成
int targetNum = needNum;
int docType = outList.getDocType();
List<StoragePos> itemPosList = pickReels(docType,itemPosNameList,posList,targetNum);
//循环剩余的库位,查找
//int forIndex = -1;
for (StoragePos pos : posList) {
if(!itemPosNameList.contains(pos.getPosName())){
itemPosList.add(pos);
itemPosNameList.add(pos.getPosName());
targetNum -= pos.getBarcode().getAmount();
if (targetNum <= 0) {
break;
}
}
for (StoragePos storagePos : itemPosList) {
itemPosNameList.add(storagePos.getPosName());
targetNum -= storagePos.getBarcode().getAmount();
}
//判断数量是否满足
if (targetNum > 0) {
int outNum = needNum - targetNum;
......@@ -336,7 +329,7 @@ public class OutListCache implements ITaskListener {
task.setOutType(4);
}
task.setLightColor(ORDER_COLOR.SKYBLUE.getRgb());//普通转储出库单 颜色:SKYBLUE
task.setLightColor(ORDER_COLOR.FIREBRICK.getRgb());//普通转储出库单 颜色:FIREBRICK
taskService.addTaskToExecute(task);
log.info("转储出库单[" + name + "],任务数[" + taskReelCount + "]仓位【" + pos.getPosName() + "】RI=[" + pos.getBarcode().getBarcode() + "] PN=[" + outListItem.getMaterialNo() + "] Amount[" + pos.getBarcode().getAmount() +
"] 首盘[" + task.isFirstReel() + "] 截料[" + task.isNeedSplitting() + "][" + task.getNeedQty() + "]");
......@@ -374,5 +367,64 @@ public class OutListCache implements ITaskListener {
return "";
}
/**
* 1,成本中心领料-大于等于需求量最小的料盘数量
* 2,线边仓间转储出库,转外协出库,发运单出库-整盘优先原则,不足发散盘
*/
private List<StoragePos> pickReels(int docType, List<String> outPosNameList, List<StoragePos> posList, int targetNum){
List<String> excludePosNameList = new ArrayList<>(outPosNameList);
List<StoragePos> itemPickPosList = new ArrayList<>();
boolean pickMaxQtyReel = true;
if(docType == 3){
//1,成本中心领料-大于等于需求量最小的料盘数量
pickMaxQtyReel = false;
}else{
//2,线边仓间转储出库,转外协出库,发运单出库-整盘优先原则,不足发散盘
pickMaxQtyReel = true;
}
do {
StoragePos outPos = pickOneReel(excludePosNameList,posList,targetNum, pickMaxQtyReel);
if(outPos == null){
break;
}else{
log.info("挑选到批次["+outPos.getBarcode().getBatch()+"]物料:" + outPos.getBarcode().getBarcode() + " 数量:" + outPos.getBarcode().getAmount());
itemPickPosList.add(outPos);
excludePosNameList.add(outPos.getPosName());
targetNum = targetNum - outPos.getBarcode().getAmount();
if(targetNum <=0){
break;
}
}
} while(true);
return itemPickPosList;
}
private StoragePos pickOneReel(List<String> excluedPosNameList, List<StoragePos> posList, int targetNum, boolean pickMaxQtyReel){
StoragePos outPos = null;
if(targetNum > 0){
for (StoragePos pos : posList) {
if(!excluedPosNameList.contains(pos.getPosName())){
if(outPos == null){
//先取第一盘(数量最大的盘)
outPos = pos;
if(pickMaxQtyReel){
return outPos;
}
}
int qty = pos.getBarcode().getAmount();
if(qty < outPos.getBarcode().getAmount() && qty >= targetNum){
//如果当前盘小于已挑料盘并且这盘料出库后可以满足需求,那么替换已挑料盘
outPos = pos;
}
if(qty < targetNum){
//当前料盘挑完还不满足需求
return outPos;
}
}
}
}
return outPos;
}
}
......@@ -600,9 +600,9 @@ public class StoragePosManagerImpl implements IStoragePosManager {
}
Query q = new Query(c);
//数量从大到小,出库先进先出
Sort sort = Sort.by(Sort.Direction.ASC, "barcode.amount");
Sort sort = Sort.by(Sort.Direction.DESC, "barcode.amount");
sort.and(Sort.by(Sort.Direction.ASC, "barcode.batch"));
sort.and(Sort.by(Sort.Direction.ASC, "canCheckOutTime"));
//sort.and(Sort.by(Sort.Direction.ASC, "canCheckOutTime"));
q.with(sort);
List<StoragePos> posList = storagePosDao.findByQuery(q);
if (posList == null || posList.size() <= 0) {
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!