Commit ea5f0a85 张少辉

1.合并库位功能开发

1 个父辈 9849e05c
......@@ -235,6 +235,7 @@ public class MenuInit {
Menu poutSet = Menu.CreatePMenu("设置", 13, "system","system",null);
addDefaultFunctionMenu(101, poutSet, "设备管理", "bunker", "storage/storage/index", "database",DEFAULT_SHOW_MENU);
addDefaultFunctionMenu(102,poutSet, "库位管理", "storagePos", "storagePos/storagePos/index", "tree-table",DEFAULT_SHOW_MENU);
addDefaultFunctionMenu(103,poutSet, "合并库位", "selectDevice", "neolight/selectDevice/index", "selectDevice");
addDefaultFunctionMenu(103, poutSet, "菜单管理", "menu", "system/menu/index", "menu");
// Menu sysSetting = new Menu(, "barcode", "条码设置", "barcodeSetting", "system/barcodeSetting/index", "database");
// Menu outSet = new Menu(, "outSetting", "出库策略", "outSetting", "system/outSetting/index", "outSet");
......
......@@ -666,7 +666,7 @@ public class HttpHelper {
List<NameValuePair> params = toNameValuePair(paramMap);
URI uri = new URIBuilder(url).setParameters(params).build();
log.info("getParam请求,地址为:"+uri);
//log.info("getParam请求,地址为:"+uri);
HttpGet httpGet = new HttpGet(uri);
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECTION_TIMEOUT).build();
httpGet.setConfig(requestConfig);
......
......@@ -9,6 +9,7 @@ import com.neotel.smfcore.core.api.bean.CodeValidateParam;
import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.inList.service.po.InList;
import com.neotel.smfcore.core.order.service.po.LiteOrder;
import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.core.system.service.po.DataLog;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
......@@ -85,6 +86,12 @@ public class SmfApi {
@Value("${api.deviceStatusUrl:}")
protected String deviceStatusUrl = "";
@Value("${api.mergePosUrl:}")
protected String mergePosUrl = "";
@Value("${api.splitPosUrl:}")
protected String splitPosUrl = "";
@PostConstruct
public void init(){
apiName = dataCache.getConfigCache("api.name",apiName);
......@@ -100,6 +107,8 @@ public class SmfApi {
fetchOrderUrl = dataCache.getConfigCache("api.fetchOrderUrl",fetchOrderUrl);
loginCheckUrl=dataCache.getConfigCache("api.loginCheckUrl",loginCheckUrl);
deviceStatusUrl=dataCache.getConfigCache("api.deviceStatusUrl",deviceStatusUrl);
mergePosUrl = dataCache.getConfigCache("api.mergePosUrl",mergePosUrl);
splitPosUrl = dataCache.getConfigCache("api.splitPosUrl",splitPosUrl);
}
/**
......@@ -294,6 +303,37 @@ public class SmfApi {
}
return true;
}
public void splitPos(String splitPosName) {
if(isUrlExist(splitPosUrl)){
threadPool.execute(new Runnable() {
@Override
public void run() {
for (ISmfApiListener apiListener : apiListenerList) {
if(apiListener.isForThisApi(apiName)){
apiListener.splitPos(splitPosUrl,splitPosName);
}
}
}
});
}
}
public void mergePos(StoragePos storagePos) {
if(isUrlExist(mergePosUrl)){
threadPool.execute(new Runnable() {
@Override
public void run() {
for (ISmfApiListener apiListener : apiListenerList) {
if(apiListener.isForThisApi(apiName)){
apiListener.mergePos(mergePosUrl,storagePos);
}
}
}
});
}
}
public String getApiName(){
return apiName;
}
......
......@@ -20,6 +20,7 @@ import com.neotel.smfcore.core.inList.util.InListCache;
import com.neotel.smfcore.core.order.LiteOrderCache;
import com.neotel.smfcore.core.order.service.manager.ILiteOrderManager;
import com.neotel.smfcore.core.order.service.po.LiteOrder;
import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.core.system.service.po.DataLog;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
......@@ -152,4 +153,14 @@ public abstract class BaseSmfApiListener implements ISmfApiListener {
public boolean deviceStatusChanges(String deviceStatusUrl, String[] cids,Integer[] status) {
return true;
}
@Override
public void splitPos(String splitPosUrl, String splitPosName) {
}
@Override
public void mergePos(String mergePosUrl, StoragePos storagePos) {
}
}
......@@ -6,6 +6,7 @@ import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.api.bean.CodeValidateParam;
import com.neotel.smfcore.core.inList.service.po.InList;
import com.neotel.smfcore.core.order.service.po.LiteOrder;
import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.core.system.service.po.DataLog;
public interface ISmfApiListener {
......@@ -80,4 +81,9 @@ public interface ISmfApiListener {
* @return
*/
boolean deviceStatusChanges(String deviceStatusUrl, String[] cids,Integer[] status );
void splitPos(String splitPosUrl, String splitPosName);
void mergePos(String mergePosUrl, StoragePos storagePos);
}
package com.neotel.smfcore.core.storage.rest;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.neotel.smfcore.common.bean.PageData;
import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.common.utils.QueryHelp;
import com.neotel.smfcore.common.utils.ReelLockPosUtil;
import com.neotel.smfcore.common.utils.StringUtils;
import com.neotel.smfcore.core.api.SmfApi;
import com.neotel.smfcore.core.barcode.enums.BARCODE_SOURCE;
import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.storage.rest.dto.StoragePosDto;
import com.neotel.smfcore.core.storage.rest.mapstruct.StoragePosMapper;
import com.neotel.smfcore.core.storage.rest.query.StoragePosQueryCriteria;
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.StoragePos;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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.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 java.util.*;
import java.util.stream.Collectors;
@Api(tags = "库位合并")
@Slf4j
@RestController
@RequestMapping("/storagePosMerge")
public class StoragePosMergeController {
@Autowired
private IStoragePosManager storagePosManager;
@Autowired
private DataCache dataCache;
@Autowired
private StoragePosMapper storagePosMapper;
@Autowired
private SmfApi smfApi;
@ApiOperation("查询所有库位")
@GetMapping("findAllPos")
public ResultBean findAllPos(StoragePosQueryCriteria criteria) {
if (criteria.getStorageIdList() != null && criteria.getStorageIdList().contains("0")) {
criteria.setStorageIdList(null);
}
String blurry = criteria.getBlurry();
if (!Strings.isNullOrEmpty(blurry)) {
blurry = blurry.substring(blurry.indexOf("-") + 1);
criteria.setBlurry(blurry);
}
Query query = QueryHelp.getQuery(criteria);
List<String> storageIdList = criteria.getStorageIdList();
if (storageIdList == null || storageIdList.isEmpty()) {
List<String> notFindStorageId = new ArrayList<>();
Collection<Storage> storages = dataCache.getAllStorage().values();
String pageType = criteria.getType();
for (Storage storage : storages) {
if (BARCODE_SOURCE.VIRTUAL.equals(pageType)) {
if (!storage.isVirtual()) {
notFindStorageId.add(storage.getId());
}
} else {
if (storage.isVirtual()) {
notFindStorageId.add(storage.getId());
}
}
}
if (!notFindStorageId.isEmpty()) {
query.addCriteria(Criteria.where("storageId").nin(notFindStorageId));
}
}
List<StoragePos> storagePosList = storagePosManager.findByQuery(query);
List<StoragePosDto> storagePosDtoList = storagePosMapper.toDto(storagePosList);
Set<String> allLockPosIds = ReelLockPosUtil.getAllLockPosIds();
for (int i = 0; i < storagePosDtoList.size(); i++) {
Storage storage = dataCache.getStorageById(storagePosDtoList.get(i).getStorageId());
if (storage != null) {
storagePosDtoList.get(i).setStorageName(storage.getName());
if (allLockPosIds.contains(storagePosDtoList.get(i).getId())) {
storagePosDtoList.get(i).setLock(true);
}
}
}
return ResultBean.newOkResult(storagePosDtoList);
}
@ApiOperation("库位合并")
@RequestMapping("mergePos")
public ResultBean mergePos(@RequestBody Map<String,String> paramMap) {
String mergePosListStr = paramMap.get("mergePosList");
String mergeNumStr = paramMap.get("mergeNum");
String storageId = paramMap.get("storageId");
if (StringUtils.isEmpty(mergePosListStr)){
return ResultBean.newErrorResult(-1,"smfcore.pos.merge.notNull","库位不能为空");
}
List<String> mergePosList = JSONObject.parseArray(mergePosListStr,String.class);
if (mergePosList == null){
mergePosList = new ArrayList<>();
}
int mergeNum = Integer.parseInt(mergeNumStr);
//判断库位与传入的值,必须一致
if (mergePosList.size() != mergeNum){
return ResultBean.newErrorResult(-1,"smfcore.pos.merge.numError","请选择[{0}]个要合并的库位",new String[]{mergeNumStr});
}
List<StoragePos> storagePosList = storagePosManager.findPosList(storageId, mergePosList);
//判断是否有物料
for (StoragePos pos : storagePosList) {
if (pos.getBarcode() != null){
return ResultBean.newErrorResult(-1,"smfcore.pos.merge.hasMaterial","库位[{0}]有物料,不能合并",new String[]{pos.getPosName()});
}
List<String> mergePosNameList = pos.getMergePosList();
if (mergePosNameList != null && !mergePosNameList.isEmpty()){
return ResultBean.newErrorResult(-1,"smfcore.pos.merge.hasMergePos","库位[{0}]已合并,不能继续合并",new String[]{pos.getPosName()});
}
}
//判断是否为相邻的库位
storagePosList = storagePosList.stream().sorted(Comparator.comparing(StoragePos::getLayer).thenComparing(StoragePos::getColumn)).collect(Collectors.toList());
boolean isSameLayerAndAdjacent = isAllSameLayerAndAdjacent(storagePosList);
if (!isSameLayerAndAdjacent){
return ResultBean.newErrorResult(-1,"smfcore.pos.merge.notAdjacent","请选择相邻的库位合并");
}
//设置合并库位信息
StoragePos storagePos = storagePosList.get(0);
List<String> mergePosNameList = new ArrayList<>();
for (StoragePos pos : storagePosList) {
mergePosNameList.add(pos.getPosName());
}
storagePos.setMergePosList(mergePosNameList);
storagePosManager.saveMergePos(storagePos);
smfApi.mergePos(storagePos);
return ResultBean.newOkResult("");
}
@ApiOperation("库位拆分")
@RequestMapping("splitPos")
public ResultBean splitPos(@RequestBody Map<String,String> paramMap) {
String splitPosName = paramMap.get("splitPosName");
if (StringUtils.isEmpty(splitPosName)){
return ResultBean.newErrorResult(-1,"smfcore.pos.split.notNull","库位不能为空");
}
StoragePos pos = storagePosManager.getByPosName(splitPosName);
if (pos == null){
return ResultBean.newErrorResult(-1,"smfcore.pos.split.notNull","库位不能为空");
}
List<String> mergePosList = pos.getMergePosList();
if (mergePosList == null || mergePosList.isEmpty()){
return ResultBean.newErrorResult(-1,"smfcore.pos.split.notMergePos","库位[{0}]未合并,不能拆分",new String[]{splitPosName});
}
if (pos.getBarcode() != null){
return ResultBean.newErrorResult(-1,"smfcore.pos.split.hasMaterial","库位[{0}]有物料,不能拆分",new String[]{splitPosName});
}
pos.setMergePosList(null);
storagePosManager.saveMergePos(pos);
smfApi.splitPos(splitPosName);
return ResultBean.newOkResult("");
}
/**
* 核心方法:传入库位列表,判断所有连续库位是否「同层 + 左右相邻」(层/列均为String类型)
* @param storagePosList 库位列表
* @return true=所有连续库位满足条件;false=不满足/列表无效
*/
public static boolean isAllSameLayerAndAdjacent(List<StoragePos> storagePosList) {
// 1. 空列表/单库位直接返回false
if (storagePosList == null || storagePosList.size() < 2) {
log.warn("库位列表为空或仅1个库位,无需判断相邻");
return false;
}
// 3. 遍历判断每一对连续库位
for (int i = 0; i < storagePosList.size() - 1; i++) {
StoragePos curr = storagePosList.get(i);
StoragePos next = storagePosList.get(i + 1);
// 转数字(空/非数字直接返回false)
Integer currLayer = strToInt(curr.getLayer());
Integer nextLayer = strToInt(next.getLayer());
Integer currCol = strToInt(curr.getColumn());
Integer nextCol = strToInt(next.getColumn());
// 4. 核心判断:层/列非空 + 同层 + 列差=1
if (currLayer == null || nextLayer == null || currCol == null || nextCol == null) {
log.warn("库位{}和{}的层/列非有效数字,不满足相邻条件", curr.getPosName(), next.getPosName());
return false;
}
if (!currLayer.equals(nextLayer)) {
log.warn("库位{}和{}不同层({} vs {}),不满足相邻条件", curr.getPosName(), next.getPosName(), curr.getLayer(), next.getLayer());
return false;
}
if (Math.abs(currCol - nextCol) != 1) {
log.warn("库位{}和{}非左右相邻(列:{} vs {}),不满足条件", curr.getPosName(), next.getPosName(), curr.getColumn(), next.getColumn());
return false;
}
}
// 所有库位满足条件
return true;
}
/**
* 内部工具:String转Integer(空/非数字返回null,避免异常)
*/
private static Integer strToInt(String str) {
if (StringUtils.isEmpty(str)) {
return null;
}
try {
return Integer.parseInt(str.trim());
} catch (NumberFormatException e) {
log.warn("字符串[{}]无法转为数字", str);
return null;
}
}
}
......@@ -107,4 +107,5 @@ public interface IStoragePosManager extends IBaseManager<StoragePos> {
StoragePos getSpEmptyPosByStorage(Storage storage, Barcode barcode, Collection<String> excludePosIds,String endStr) throws ValidateException;
void saveMergePos(StoragePos storagePos);
}
......@@ -1176,4 +1176,9 @@ public class StoragePosManagerImpl implements IStoragePosManager {
StoragePos pos = storagePosDao.findOne(query);
return pos;
}
@Override
public void saveMergePos(StoragePos storagePos) {
storagePosDao.save(storagePos);
}
}
......@@ -38,91 +38,15 @@ public class HaoBoNlpPosHandler {
@PostConstruct
private void init() {
String apiName = smfApi.getApiName();
if (haoboApi.isForThisApi(apiName)) {
scheduledThreadPool.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
String apiName = smfApi.getApiName();
if (haoboApi.isForThisApi(apiName)) {
handlePos();
handleTriColorLight();
}
}, 30, 2, TimeUnit.SECONDS);
}
}
// 新增:定义静态缓存,记录每个货架(cid)上一次点亮的灯通道
private static final Map<String, Integer> LAST_LIGHT_CHANNEL_CACHE = new HashMap<>();
private void handleTriColorLight() {
int left = 81;
int right = 82;
int buzzer = 9;
int color_green = 10;
int color_yellow = 11;
int color_red = 12;
for (Storage storage : dataCache.getAllStorage().values()) {
if (storage.isNLPHBShelf()) {
boolean hasTask = false;
boolean hasException = false;
Collection<DataLog> queueTasks = taskService.getQueueTasks(storage.getCid());
if (queueTasks != null && !queueTasks.isEmpty()) {
hasTask = true;
}
List<List<String>> lastDeviceData = DevicesStatusUtil.getDeviceData(storage.getCid());
List<String> lastHasReelPosErrorList = new ArrayList<>();
List<String> lastNoReelPosErrorList = new ArrayList<>();
if (lastDeviceData != null && lastDeviceData.size() == 2) {
lastHasReelPosErrorList = lastDeviceData.get(0);
lastNoReelPosErrorList = lastDeviceData.get(1);
}
if (lastHasReelPosErrorList != null && !lastHasReelPosErrorList.isEmpty()) {
hasException = true;
}
if (lastNoReelPosErrorList != null && !lastNoReelPosErrorList.isEmpty()) {
hasException = true;
}
int ioBoardAddress = left;
if (storage.getCid().endsWith("A")) {
ioBoardAddress = left;
} else if (storage.getCid().endsWith("B")) {
ioBoardAddress = right;
}
int channel = color_green;
if (hasException) {
channel = color_red;
} else if (!hasException && hasTask) {
channel = color_yellow;
} else {
channel = color_green;
}
// ===== 核心修改:首次无缓存则全部关闭,非首次关闭上一个灯 =====
String cid = storage.getCid();
Integer lastChannel = LAST_LIGHT_CHANNEL_CACHE.get(cid);
if (lastChannel == null) {
// 第一次操作:全部关闭绿、黄、红三个通道
haoboApi.controlIoBoard(ioBoardAddress, color_green, false);
haoboApi.controlIoBoard(ioBoardAddress, color_yellow, false);
haoboApi.controlIoBoard(ioBoardAddress, color_red, false);
} else if (lastChannel != channel) {
// 非首次且通道不同:仅关闭上一次点亮的灯
haoboApi.controlIoBoard(ioBoardAddress, lastChannel, false);
}
// 点亮本次目标灯(原有逻辑保留)
if(lastChannel == null || lastChannel != channel ){
haoboApi.controlIoBoard(ioBoardAddress, channel, true);
}
// 更新缓存,记录本次点亮的通道
LAST_LIGHT_CHANNEL_CACHE.put(cid, channel);
// ==============================================
}
}
}, 30, 5, TimeUnit.SECONDS);
}
private void handlePos() {
......@@ -147,7 +71,6 @@ public class HaoBoNlpPosHandler {
List<String> totalAddList = posTotalDiffResult.getTotalAddList();
List<String> totalReduceList = posTotalDiffResult.getTotalReduceList();
haoboApi.lightUpSomeLampBeads(totalAddList, totalReduceList);
DevicesStatusUtil.updateDeviceData(cid, newData);
}
}
......
......@@ -9,6 +9,7 @@ import com.neotel.smfcore.common.utils.StringUtils;
import com.neotel.smfcore.core.api.listener.BaseSmfApiListener;
import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.order.enums.ORDER_COLOR;
import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.custom.haobo.bean.response.GetInventoryResponse;
import lombok.extern.slf4j.Slf4j;
......@@ -91,6 +92,39 @@ public class HaoboApi extends BaseSmfApiListener {
}
}
@Override
public void mergePos(String mergePosUrl, StoragePos storagePos) {
List<String> mergePosList = storagePos.getMergePosList();
Map<String,Object> paramMap = new HashMap<>();
paramMap.put("locationList",mergePosList);
paramMap.put("oneMergedQuantity",mergePosList.size());
log.info("合并料架,请求浩博料架,地址为:"+mergePosUrl+",参数为:"+ JSON.toJSONString(paramMap));
try {
String result = HttpHelper.postJson(mergePosUrl, paramMap);
log.info("合并料架,浩博料架返回结果为:"+result);
} catch (ApiException e) {
log.info("合并料架,浩博料架返回异常,异常信息为:"+e.getMessage());
}
}
@Override
public void splitPos(String splitPosUrl, String splitPosName) {
/**
* {"locationList":["T001A1001"]}
*/
Map<String,Object> paramMap = new HashMap<>();
paramMap.put("locationList",Collections.singletonList(splitPosName));
log.info("拆分料架,请求浩博料架,地址为:"+splitPosUrl+",参数为:"+ JSON.toJSONString(paramMap));
try {
String result = HttpHelper.postJson(splitPosUrl, paramMap);
log.info("拆分料架,浩博料架返回结果为:"+result);
} catch (ApiException e) {
log.info("拆分料架,浩博料架返回异常,异常信息为:"+e.getMessage());
}
}
protected List<String> getInventoryPosName(String cid) {
List<String> hasReelPosNameList = new ArrayList<>();
Map<String, Object> paramMap = new HashMap<>();
......
......@@ -158,7 +158,7 @@ public class HaoboNlpController {
storagePos.setBarcode(barcode);
storagePos.setUsed(true);
storagePos.setCanCheckOutTime(System.currentTimeMillis());
storagePosManager.save(storagePos);
storagePosManager.saveMergePos(storagePos);
if (barcode != null) {
dataCache.updateInventory(storagePos, barcode);
//记录日志,完成 task
......@@ -210,7 +210,7 @@ public class HaoboNlpController {
storagePos.setBarcode(null);
storagePos.setUsed(false);
storagePosManager.save(storagePos);
storagePosManager.saveMergePos(storagePos);
log.info("出库完成,清空仓位: " + storagePos.getId() + "[" + storagePos.getPosName() + "]");
......
......@@ -463,4 +463,11 @@ smfcore.reelPosMove.posIsNull=\u5E93\u4F4D[{1}]\u4E3A\u7A7A
smfcore.liteOrder.exist=\u9700\u6C42\u5355{0}\u5DF2\u5B58\u5728
smfcore.reelPosMove.barcodeError=\u5E93\u4F4D{0}\u6761\u7801\u4E3A{1}\uFF0C\u4E0E\u79FB\u5E93\u6761\u7801{1}\u4E0D\u4E00\u81F4
smfcore.barcode.notFindFeerder=\u672A\u627E\u5230[{0}]\u7AD9\u4F4D\u4FE1\u606F
smfcore.pos.merge.notNull=\u5E93\u4F4D\u4E0D\u80FD\u4E3A\u7A7A
smfcore.pos.merge.numError=\u8BF7\u9009\u62E9[{0}]\u4E2A\u8981\u5408\u5E76\u7684\u5E93\u4F4D
smfcore.pos.merge.hasMaterial=\u5E93\u4F4D[{0}]\u6709\u7269\u6599,\u4E0D\u80FD\u5408\u5E76
smfcore.pos.merge.hasMergePos=\u5E93\u4F4D[{0}]\u5DF2\u5408\u5E76,\u4E0D\u80FD\u7EE7\u7EED\u5408\u5E76
smfcore.pos.merge.notAdjacent=\u8BF7\u9009\u62E9\u76F8\u90BB\u7684\u5E93\u4F4D\u5408\u5E76
smfcore.pos.split.notNull=\u5E93\u4F4D\u4E0D\u80FD\u4E3A\u7A7A
smfcore.pos.split.notMergePos=\u5E93\u4F4D[{0}]\u672A\u5408\u5E76,\u4E0D\u80FD\u62C6\u5206
smfcore.pos.split.hasMaterial=\u5E93\u4F4D[{0}]\u6709\u7269\u6599,\u4E0D\u80FD\u62C6\u5206
......@@ -453,3 +453,11 @@ smfcore.liteOrder.exist=Bedarfsauftrag {0} existiert bereits
smfcore.reelPosMove.barcodeError=Der Barcode des Lagerorts {0} ist {1}, nicht identisch mit dem Umzugscode {1}
smfcore.barcode.notFindFeerder=Stationsinformation [{0}] nicht gefunden
smfcore.storagePos.provider=Lieferant
smfcore.pos.merge.notNull=Lagerposition darf nicht leer sein
smfcore.pos.merge.numError=W\u00E4hlen Sie [{0}] Lagerpositionen zum Zusammenf\u00FChren aus
smfcore.pos.merge.hasMaterial=Lagerposition [{0}] enth\u00E4lt Materialien und kann nicht zusammengef\u00FChrt werden
smfcore.pos.merge.hasMergePos=Lagerposition [{0}] wurde bereits zusammengef\u00FChrt und kann nicht weiter zusammengef\u00FChrt werden
smfcore.pos.merge.notAdjacent=W\u00E4hlen Sie benachbarte Lagerpositionen zum Zusammenf\u00FChren aus
smfcore.pos.split.notNull=Lagerposition darf nicht leer sein
smfcore.pos.split.notMergePos=Lagerposition [{0}] wurde nicht zusammengef\u00FChrt und kann nicht aufgeteilt werden
smfcore.pos.split.hasMaterial=Lagerposition [{0}] enth\u00E4lt Materialien und kann nicht aufgeteilt werden
......@@ -454,3 +454,11 @@ smfcore.liteOrder.exist=Requirement order {0} already exists
smfcore.reelPosMove.barcodeError=Location {0} barcode is {1}, inconsistent with the transfer barcode {1}
smfcore.barcode.notFindFeerder=Station information [{0}] not found
smfcore.storagePos.provider=Provider
smfcore.pos.merge.notNull=Storage position cannot be empty
smfcore.pos.merge.numError=Please select [{0}] storage positions to merge
smfcore.pos.merge.hasMaterial=Storage position [{0}] contains materials and cannot be merged
smfcore.pos.merge.hasMergePos=Storage position [{0}] has been merged and cannot be merged further
smfcore.pos.merge.notAdjacent=Please select adjacent storage positions to merge
smfcore.pos.split.notNull=Storage position cannot be empty
smfcore.pos.split.notMergePos=Storage position [{0}] has not been merged and cannot be split
smfcore.pos.split.hasMaterial=Storage position [{0}] contains materials and cannot be split
......@@ -453,3 +453,11 @@ smfcore.liteOrder.exist=Le bon de commande {0} existe d\u00E9j\u00E0
smfcore.reelPosMove.barcodeError=Le code-barres de l'emplacement {0} est {1}, incompatible avec le code-barres de transfert {1}
smfcore.barcode.notFindFeerder=Informations de station [{0}] non trouv\u00E9es
smfcore.storagePos.provider=Fournisseur
smfcore.pos.merge.notNull=L'emplacement de stockage ne peut pas \u00EAtre vide
smfcore.pos.merge.numError=Veuillez s\u00E9lectionner [{0}] emplacements de stockage \u00E0 fusionner
smfcore.pos.merge.hasMaterial=L'emplacement de stockage [{0}] contient des mati\u00E8res et ne peut pas \u00EAtre fusionn\u00E9
smfcore.pos.merge.hasMergePos=L'emplacement de stockage [{0}] a d\u00E9j\u00E0 \u00E9t\u00E9 fusionn\u00E9 et ne peut pas \u00EAtre fusionn\u00E9 davantage
smfcore.pos.merge.notAdjacent=Veuillez s\u00E9lectionner des emplacements de stockage adjacents \u00E0 fusionner
smfcore.pos.split.notNull=L'emplacement de stockage ne peut pas \u00EAtre vide
smfcore.pos.split.notMergePos=L'emplacement de stockage [{0}] n'a pas \u00E9t\u00E9 fusionn\u00E9 et ne peut pas \u00EAtre divis\u00E9
smfcore.pos.split.hasMaterial=L'emplacement de stockage [{0}] contient des mati\u00E8res et ne peut pas \u00EAtre divis\u00E9
......@@ -450,3 +450,11 @@ smfcore.liteOrder.exist=\u8981\u6C42\u5358 {0} \u306F\u65E2\u306B\u5B58\u5728\u3
smfcore.reelPosMove.barcodeError=\u5EAB\u4F4D {0} \u306E\u30D0\u30FC\u30B3\u30FC\u30C9\u306F {1} \u3067\u3001\u79FB\u5EAB\u30D0\u30FC\u30B3\u30FC\u30C9 {1} \u3068\u4E0D\u4E00\u81F4\u3067\u3059
smfcore.barcode.notFindFeerder=[{0}]\u30B9\u30C6\u30FC\u30B7\u30E7\u30F3\u60C5\u5831\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
smfcore.storagePos.provider=\u4F9B\u7D66\u8005
smfcore.pos.merge.notNull=\u68DA\u4F4D\u7F6E\u3092\u7A7A\u306B\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093
smfcore.pos.merge.numError=\u7D71\u5408\u3059\u308B\u68DA\u4F4D\u7F6E\u3092[{0}]\u3064\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044
smfcore.pos.merge.hasMaterial=\u68DA\u4F4D\u7F6E[{0}]\u306B\u8CC7\u6750\u304C\u3042\u308B\u305F\u3081\u3001\u7D71\u5408\u3067\u304D\u307E\u305B\u3093
smfcore.pos.merge.hasMergePos=\u68DA\u4F4D\u7F6E[{0}]\u306F\u65E2\u306B\u7D71\u5408\u3055\u308C\u3066\u3044\u308B\u305F\u3081\u3001\u3055\u3089\u306B\u7D71\u5408\u3067\u304D\u307E\u305B\u3093
smfcore.pos.merge.notAdjacent=\u96A3\u63A5\u3059\u308B\u68DA\u4F4D\u7F6E\u3092\u9078\u629E\u3057\u3066\u7D71\u5408\u3057\u3066\u304F\u3060\u3055\u3044
smfcore.pos.split.notNull=\u68DA\u4F4D\u7F6E\u3092\u7A7A\u306B\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093
smfcore.pos.split.notMergePos=\u68DA\u4F4D\u7F6E[{0}]\u306F\u7D71\u5408\u3055\u308C\u3066\u3044\u306A\u3044\u305F\u3081\u3001\u5206\u5272\u3067\u304D\u307E\u305B\u3093
smfcore.pos.split.hasMaterial=\u68DA\u4F4D\u7F6E[{0}]\u306B\u8CC7\u6750\u304C\u3042\u308B\u305F\u3081\u3001\u5206\u5272\u3067\u304D\u307E\u305B\u3093
......@@ -450,3 +450,11 @@ smfcore.liteOrder.exist=\u9700\u6C42\u5355{0}\u5DF2\u5B58\u5728
smfcore.reelPosMove.barcodeError=\u5E93\u4F4D{0}\u6761\u7801\u4E3A{1}\uFF0C\u4E0E\u79FB\u5E93\u6761\u7801{1}\u4E0D\u4E00\u81F4
smfcore.barcode.notFindFeerder=\u672A\u627E\u5230[{0}]\u7AD9\u4F4D\u4FE1\u606F
smfcore.storagePos.provider=\u4F9B\u5E94\u5546
smfcore.pos.merge.notNull=\u5E93\u4F4D\u4E0D\u80FD\u4E3A\u7A7A
smfcore.pos.merge.numError=\u8BF7\u9009\u62E9[{0}]\u4E2A\u8981\u5408\u5E76\u7684\u5E93\u4F4D
smfcore.pos.merge.hasMaterial=\u5E93\u4F4D[{0}]\u6709\u7269\u6599,\u4E0D\u80FD\u5408\u5E76
smfcore.pos.merge.hasMergePos=\u5E93\u4F4D[{0}]\u5DF2\u5408\u5E76,\u4E0D\u80FD\u7EE7\u7EED\u5408\u5E76
smfcore.pos.merge.notAdjacent=\u8BF7\u9009\u62E9\u76F8\u90BB\u7684\u5E93\u4F4D\u5408\u5E76
smfcore.pos.split.notNull=\u5E93\u4F4D\u4E0D\u80FD\u4E3A\u7A7A
smfcore.pos.split.notMergePos=\u5E93\u4F4D[{0}]\u672A\u5408\u5E76,\u4E0D\u80FD\u62C6\u5206
smfcore.pos.split.hasMaterial=\u5E93\u4F4D[{0}]\u6709\u7269\u6599,\u4E0D\u80FD\u62C6\u5206
......@@ -450,3 +450,11 @@ smfcore.liteOrder.exist=\u9700\u6C42\u55AE {0} \u5DF2\u5B58\u5728
smfcore.reelPosMove.barcodeError=\u5EAB\u4F4D {0} \u689D\u78BC\u70BA {1}\uFF0C\u8207\u79FB\u5EAB\u689D\u78BC {1} \u4E0D\u4E00\u81F4
smfcore.barcode.notFindFeerder=\u672A\u627E\u5230[{0}]\u7AD9\u4F4D\u8CC7\u8A0A
smfcore.storagePos.provider=\u4F9B\u7D66\u8005
smfcore.pos.merge.notNull=\u5EAB\u4F4D\u4E0D\u80FD\u70BA\u7A7A
smfcore.pos.merge.numError=\u8ACB\u9078\u64C7[{0}]\u500B\u8981\u5408\u4F75\u7684\u5EAB\u4F4D
smfcore.pos.merge.hasMaterial=\u5EAB\u4F4D[{0}]\u6709\u7269\u6599,\u4E0D\u80FD\u5408\u4F75
smfcore.pos.merge.hasMergePos=\u5EAB\u4F4D[{0}]\u5DF2\u5408\u4F75,\u4E0D\u80FD\u7E7C\u7E8C\u5408\u4F75
smfcore.pos.merge.notAdjacent=\u8ACB\u9078\u64C7\u76F8\u9130\u7684\u5EAB\u4F4D\u5408\u4F75
smfcore.pos.split.notNull=\u5EAB\u4F4D\u4E0D\u80FD\u70BA\u7A7A
smfcore.pos.split.notMergePos=\u5EAB\u4F4D[{0}]\u672A\u5408\u4F75,\u4E0D\u80FD\u62C6\u5206
smfcore.pos.split.hasMaterial=\u5EAB\u4F4D[{0}]\u6709\u7269\u6599,\u4E0D\u80FD\u62C6\u5206
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!