Skip to content
切换导航条
切换导航条
当前项目
正在载入...
登录
孙克
/
smf-core
转到一个项目
切换导航栏
切换导航栏固定状态
项目
群组
代码片段
帮助
项目
活动
版本库
流水线
图表
问题
0
合并请求
0
维基
网络
创建新的问题
作业
提交
问题看板
文件
提交
网络
比较
分支
标签
Commit 85cba47b
由
张少辉
编写于
2026-01-14 17:13:39 +0800
浏览文件
选项
浏览文件
标签
下载
电子邮件补丁
差异文件
1.成品仓功能开发
1 个父辈
5d02d793
隐藏空白字符变更
内嵌
并排
正在显示
11 个修改的文件
包含
767 行增加
和
0 行删除
src/main/java/com/neotel/smfcore/common/utils/Constants.java
src/main/java/com/neotel/smfcore/core/storage/service/manager/IStoragePosManager.java
src/main/java/com/neotel/smfcore/core/storage/service/manager/impl/StoragePosManagerImpl.java
src/main/java/com/neotel/smfcore/custom/aiqingzhiyin1643/finishedGoodsWarehouse/bean/PutAwayLocInfo.java
src/main/java/com/neotel/smfcore/custom/aiqingzhiyin1643/finishedGoodsWarehouse/bean/PutOutLocInfo.java
src/main/java/com/neotel/smfcore/custom/aiqingzhiyin1643/finishedGoodsWarehouse/controller/AgvFgDeviceController.java
src/main/java/com/neotel/smfcore/custom/aiqingzhiyin1643/finishedGoodsWarehouse/controller/PutAwayController.java
src/main/java/com/neotel/smfcore/custom/aiqingzhiyin1643/finishedGoodsWarehouse/controller/PutOutController.java
src/main/java/com/neotel/smfcore/custom/aiqingzhiyin1643/finishedGoodsWarehouse/enums/PutAwayLocEnum.java
src/main/java/com/neotel/smfcore/custom/aiqingzhiyin1643/finishedGoodsWarehouse/enums/PutOutLocEnum.java
src/main/java/com/neotel/smfcore/custom/aiqingzhiyin1643/finishedGoodsWarehouse/util/PutOutLocInfoCache.java
src/main/java/com/neotel/smfcore/common/utils/Constants.java
查看文件 @
85cba47
...
...
@@ -219,4 +219,8 @@ public class Constants {
*/
public
static
final
String
Cache_ShelfInfo
=
"Cache_ShelfInfo"
;
/**
* 缓存的出口信息
*/
public
static
final
String
Cache_PutOutLoc_Info
=
"Cache_PutOutLoc_Info"
;
}
src/main/java/com/neotel/smfcore/core/storage/service/manager/IStoragePosManager.java
查看文件 @
85cba47
...
...
@@ -102,4 +102,6 @@ public interface IStoragePosManager extends IBaseManager<StoragePos> {
int
getRemainPosCountByStorage
(
Storage
storage
,
Barcode
barcode
,
Collection
<
String
>
excludePosIds
,
String
s
,
String
f
);
StoragePos
getByPidBarcode
(
String
reelId
);
StoragePos
findFgWarehouseForPutIn
(
Storage
fgWarehouseStorage
,
Barcode
barcode
,
Collection
<
String
>
strings
,
boolean
heightLimited
);
}
src/main/java/com/neotel/smfcore/core/storage/service/manager/impl/StoragePosManagerImpl.java
查看文件 @
85cba47
...
...
@@ -398,6 +398,48 @@ public class StoragePosManagerImpl implements IStoragePosManager {
}
@Override
public
StoragePos
findFgWarehouseForPutIn
(
Storage
storage
,
Barcode
barcode
,
Collection
<
String
>
excludePosIds
,
boolean
heightLimited
)
{
Criteria
c
=
Criteria
.
where
(
"storageId"
).
is
(
storage
.
getId
());
COMPATIBLE_TYPE
compatibleType
=
storage
.
getCompatibleType
();
if
(
compatibleType
==
COMPATIBLE_TYPE
.
EXACT_MATCH
)
{
//完全匹配
c
=
c
.
and
(
"w"
).
is
(
barcode
.
getPlateSize
()).
and
(
"h"
).
is
(
barcode
.
getHeight
());
}
else
if
(
compatibleType
==
COMPATIBLE_TYPE
.
FULLY_COMPATIBLE
)
{
//完全兼容
c
=
c
.
and
(
"w"
).
gte
(
barcode
.
getPlateSize
()).
and
(
"h"
).
gte
(
barcode
.
getHeight
());
//宽度大于等于料盘宽度,高度大于等于料盘高度
}
else
if
(
compatibleType
==
COMPATIBLE_TYPE
.
SIZE_COMPATIBLE
)
{
//同尺寸兼容
c
=
c
.
and
(
"w"
).
is
(
barcode
.
getPlateSize
()).
and
(
"h"
).
gte
(
barcode
.
getHeight
());
//宽度等于料盘宽度,高度大于等于料盘高度
}
else
if
(
compatibleType
==
COMPATIBLE_TYPE
.
W13_15_COMPATIBLE
)
{
//13/15寸兼容,如果是13寸盘,可以放15寸,其他按照同尺寸兼容
if
(
barcode
.
getPlateSize
()
==
13
)
{
c
=
c
.
and
(
"w"
).
in
(
barcode
.
getPlateSize
(),
15
).
and
(
"h"
).
gte
(
barcode
.
getHeight
());
}
else
{
c
=
c
.
and
(
"w"
).
is
(
barcode
.
getPlateSize
()).
and
(
"h"
).
gte
(
barcode
.
getHeight
());
//宽度等于料盘宽度,高度大于等于料盘高度
}
}
c
=
c
.
and
(
"enabled"
).
is
(
true
)
//可用
.
and
(
"used"
).
is
(
false
);
//未使用
//去除的仓位
if
(
excludePosIds
!=
null
&&
!
excludePosIds
.
isEmpty
())
{
c
=
c
.
and
(
"id"
).
nin
(
excludePosIds
);
}
//判断有没有限高
//判断有没有限高
if
(
heightLimited
){
// 限高:匹配仓位编码最后以-03结尾(请确认字段名是posCode,若不是请替换)
Pattern
pattern
=
Pattern
.
compile
(
"-03$"
);
c
=
c
.
and
(
"posName"
).
regex
(
pattern
);
}
else
{
// 不限高:匹配仓位编码最后不是-03结尾
Pattern
pattern
=
Pattern
.
compile
(
"^(.*(?<!-03))$"
);
c
=
c
.
and
(
"posName"
).
regex
(
pattern
);
}
Query
query
=
new
Query
(
c
);
//优先放入最合适的位置(根据尺寸),相同尺寸按优先级排序
query
.
with
(
Sort
.
by
(
Sort
.
Direction
.
ASC
,
"w"
).
and
(
Sort
.
by
(
Sort
.
Direction
.
ASC
,
"h"
)).
and
(
Sort
.
by
(
Sort
.
Direction
.
DESC
,
"priority"
)));
StoragePos
pos
=
storagePosDao
.
findOne
(
query
);
return
pos
;
}
@Override
public
PageData
<
StoragePos
>
findByPage
(
Query
query
,
Pageable
pageable
)
{
int
totalCount
=
storagePosDao
.
countByQuery
(
query
);
List
<
StoragePos
>
list
=
storagePosDao
.
findByQuery
(
query
,
pageable
);
...
...
src/main/java/com/neotel/smfcore/custom/aiqingzhiyin1643/finishedGoodsWarehouse/bean/PutAwayLocInfo.java
0 → 100644
查看文件 @
85cba47
package
com
.
neotel
.
smfcore
.
custom
.
aiqingzhiyin1643
.
finishedGoodsWarehouse
.
bean
;
/**
* 入库位置信息DTO:专门封装「实际位置+是否限高」,用于接口返回结构化数据
* 包路径可根据你的项目调整,例如:com.xxx.warehouse.dto
*/
public
class
PutAwayLocInfo
{
// 实际位置(对应枚举的actualPosition字段)
private
String
actualPosition
;
// 是否限高(对应枚举的heightLimited字段)
private
boolean
heightLimited
;
// 全参构造方法(用于枚举中快速封装数据)
public
PutAwayLocInfo
(
String
actualPosition
,
boolean
heightLimited
)
{
this
.
actualPosition
=
actualPosition
;
this
.
heightLimited
=
heightLimited
;
}
// 无参构造方法(可选,适配部分框架的反序列化需求)
public
PutAwayLocInfo
()
{
}
// getter/setter方法(必须,接口返回时框架需通过getter序列化字段)
public
String
getActualPosition
()
{
return
actualPosition
;
}
public
void
setActualPosition
(
String
actualPosition
)
{
this
.
actualPosition
=
actualPosition
;
}
public
boolean
isHeightLimited
()
{
return
heightLimited
;
}
public
void
setHeightLimited
(
boolean
heightLimited
)
{
this
.
heightLimited
=
heightLimited
;
}
// 可选:重写toString,便于日志打印/调试查看数据
@Override
public
String
toString
()
{
return
"PutAwayLocInfo{"
+
"actualPosition='"
+
actualPosition
+
'\''
+
", heightLimited="
+
heightLimited
+
'}'
;
}
}
\ No newline at end of file
src/main/java/com/neotel/smfcore/custom/aiqingzhiyin1643/finishedGoodsWarehouse/bean/PutOutLocInfo.java
0 → 100644
查看文件 @
85cba47
package
com
.
neotel
.
smfcore
.
custom
.
aiqingzhiyin1643
.
finishedGoodsWarehouse
.
bean
;
import
lombok.AllArgsConstructor
;
import
lombok.Data
;
@Data
@AllArgsConstructor
public
class
PutOutLocInfo
{
//配置给agv使用的名称
private
String
name
;
//实际位置
private
String
actualPosition
;
//当前绑定的料箱号
private
String
currentBindBox
;
}
\ No newline at end of file
src/main/java/com/neotel/smfcore/custom/aiqingzhiyin1643/finishedGoodsWarehouse/controller/AgvFgDeviceController.java
0 → 100644
查看文件 @
85cba47
package
com
.
neotel
.
smfcore
.
custom
.
aiqingzhiyin1643
.
finishedGoodsWarehouse
.
controller
;
import
com.neotel.smfcore.common.bean.ResultBean
;
import
com.neotel.smfcore.common.utils.ReelLockPosUtil
;
import
com.neotel.smfcore.common.utils.StringUtils
;
import
com.neotel.smfcore.core.device.enums.OP_STATUS
;
import
com.neotel.smfcore.core.device.util.DataCache
;
import
com.neotel.smfcore.core.storage.enums.CORRESPONDING_WAREHOUSE
;
import
com.neotel.smfcore.core.storage.service.po.Storage
;
import
com.neotel.smfcore.core.system.service.po.DataLog
;
import
com.neotel.smfcore.core.system.util.TaskService
;
import
com.neotel.smfcore.custom.aiqingzhiyin1643.bean.CtuCheckOutTask
;
import
com.neotel.smfcore.custom.aiqingzhiyin1643.bean.CtuPutInTask
;
import
com.neotel.smfcore.custom.aiqingzhiyin1643.finishedGoodsWarehouse.util.PutOutLocInfoCache
;
import
com.neotel.smfcore.custom.aiqingzhiyin1643.util.BoxUtil
;
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.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
javax.servlet.http.HttpServletRequest
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Comparator
;
import
java.util.List
;
import
java.util.stream.Collectors
;
@Api
(
tags
=
"成品仓agv对接"
)
@Slf4j
@RequestMapping
(
"/agvFgDevice"
)
@RestController
public
class
AgvFgDeviceController
{
@Autowired
private
TaskService
taskService
;
@Autowired
private
DataCache
dataCache
;
@Autowired
private
PutOutLocInfoCache
putOutLocInfoCache
;
@ApiOperation
(
"定时获取入库任务"
)
@RequestMapping
(
"/service/store/agvBox/getPutInTask"
)
@AnonymousAccess
public
ResultBean
getPutInTask
(
String
cid
)
{
List
<
CtuPutInTask
>
putInTaskList
=
new
ArrayList
<>();
List
<
DataLog
>
allTasks
=
taskService
.
getAllTasks
();
Storage
storage
=
dataCache
.
getStorage
(
cid
);
if
(
storage
.
getCorrespondingWarehouse
()
==
CORRESPONDING_WAREHOUSE
.
FINISHED_GOODS_WAREHOUSE
)
{
if
(
storage
!=
null
)
{
for
(
DataLog
dataLog
:
allTasks
)
{
if
(
dataLog
.
isPutInTask
()
&&
!
dataLog
.
isFinished
()
&&
!
dataLog
.
isCancel
()
&&
storage
.
getId
().
equals
(
dataLog
.
getStorageId
()))
{
CtuPutInTask
putInTask
=
new
CtuPutInTask
();
putInTask
.
setStatus
(
dataLog
.
getStatus
());
putInTask
.
setPosName
(
dataLog
.
getPosName
());
putInTask
.
setBarcode
(
dataLog
.
getBarcode
());
putInTask
.
setPutInLoc
(
dataLog
.
getCurrentLoc
());
putInTaskList
.
add
(
putInTask
);
}
}
}
}
return
ResultBean
.
newOkResult
(
putInTaskList
);
}
@ApiOperation
(
"定时获取出库库位列表"
)
@RequestMapping
(
value
=
"/service/store/agvBox/getOutTask"
)
@AnonymousAccess
public
synchronized
ResultBean
getOutTask
(
HttpServletRequest
request
)
{
List
<
CtuCheckOutTask
>
ctuCheckOutTaskList
=
new
ArrayList
<>();
String
cid
=
request
.
getParameter
(
"cid"
);
Storage
storage
=
dataCache
.
getStorage
(
cid
);
if
(
storage
!=
null
)
{
if
(
storage
.
getCorrespondingWarehouse
()
==
CORRESPONDING_WAREHOUSE
.
FINISHED_GOODS_WAREHOUSE
)
{
Collection
<
DataLog
>
queueTasks
=
taskService
.
getQueueTasks
();
queueTasks
=
queueTasks
.
stream
().
sorted
(
Comparator
.
comparing
(
DataLog:
:
getCreateDate
)).
collect
(
Collectors
.
toList
());
for
(
DataLog
queueTask
:
queueTasks
)
{
if
(
queueTask
.
isWait
()
&&
queueTask
.
isCheckOutTask
())
{
CtuCheckOutTask
ctuCheckOutTask
=
new
CtuCheckOutTask
();
ctuCheckOutTask
.
setBarcode
(
queueTask
.
getBarcode
());
ctuCheckOutTask
.
setPosName
(
queueTask
.
getPosName
());
ctuCheckOutTask
.
setStatus
(
queueTask
.
getStatus
());
String
currentLoc
=
queueTask
.
getCurrentLoc
();
if
(
StringUtils
.
isEmpty
(
currentLoc
))
{
currentLoc
=
putOutLocInfoCache
.
bindCurrentBox
(
queueTask
.
getBarcode
());
}
if
(
StringUtils
.
isNotEmpty
(
currentLoc
))
{
ctuCheckOutTask
.
setCheckOutLoc
(
currentLoc
);
ctuCheckOutTaskList
.
add
(
ctuCheckOutTask
);
}
}
}
}
}
return
ResultBean
.
newOkResult
(
ctuCheckOutTaskList
);
}
@ApiOperation
(
"修改任务接口"
)
@RequestMapping
(
value
=
"/service/store/agvBox/updateLocInfo"
)
@AnonymousAccess
public
synchronized
ResultBean
updateLocInfo
(
HttpServletRequest
request
)
{
String
rfid
=
request
.
getParameter
(
"barcode"
);
String
statusStr
=
request
.
getParameter
(
"status"
);
String
cid
=
request
.
getParameter
(
"cid"
);
String
loc
=
request
.
getParameter
(
"loc"
);
//工位
log
.
info
(
"收到料盘["
+
rfid
+
"]更新位置指令["
+
statusStr
+
"]"
+
"cid为:"
+
cid
);
if
(
statusStr
==
null
)
{
return
ResultBean
.
newErrorResult
(
301
,
"smfcore.updateLoc.status.empty"
,
"状态不能为空"
);
}
if
(
rfid
==
null
)
{
return
ResultBean
.
newErrorResult
(
302
,
"smfcore.updateLoc.barcode.empty"
,
"条码不能为空"
);
}
Storage
storage
=
dataCache
.
getStorage
(
cid
);
if
(
storage
==
null
){
return
ResultBean
.
newErrorResult
(-
1
,
""
,
"未找到对应的料仓信息"
);
}
if
(
storage
.
getCorrespondingWarehouse
()
!=
CORRESPONDING_WAREHOUSE
.
FINISHED_GOODS_WAREHOUSE
){
return
ResultBean
.
newErrorResult
(-
1
,
""
,
"请在设备管理里,配置成品仓信息"
);
}
DataLog
opTask
=
null
;
List
<
DataLog
>
allTasks
=
taskService
.
getAllTasks
();
for
(
DataLog
task
:
allTasks
)
{
if
(
rfid
.
startsWith
(
task
.
getBarcode
())
&&
storage
.
getId
().
equals
(
task
.
getStorageId
()))
{
if
(!
task
.
isCancel
()
&&
!
task
.
isFinished
())
{
opTask
=
task
;
break
;
}
}
}
if
(
opTask
==
null
)
{
return
ResultBean
.
newErrorResult
(
303
,
"smfcore.task.notExist"
,
"任务不存在"
);
}
if
(
opTask
.
isFinished
())
{
return
ResultBean
.
newErrorResult
(
304
,
"smfcore.task.hasEnd"
,
"任务已完成"
);
}
statusStr
=
statusStr
.
toUpperCase
();
log
.
info
(
"更新料箱["
+
rfid
+
"]的任务状态["
+
opTask
.
getStatus
()
+
"]为["
+
statusStr
+
"]"
+
"目的地信息为:"
+
loc
);
OP_STATUS
updateStatus
=
OP_STATUS
.
valueOf
(
statusStr
);
//如果是相同状态,则不执行
if
(
statusStr
.
equals
(
opTask
.
getStatus
()))
{
return
ResultBean
.
newOkResult
(
""
);
}
if
(
updateStatus
!=
null
)
{
opTask
.
setStatus
(
statusStr
);
if
(
opTask
.
isCheckOutTask
())
{
if
(
OP_STATUS
.
EXECUTING
.
name
().
equals
(
statusStr
))
{
//在执行队列中
taskService
.
updateQueueTask
(
opTask
);
}
else
{
taskService
.
moveTaskToFinished
(
opTask
);
if
(!
opTask
.
isOutFromPos
())
{
//从库位中取出,需要移到完成队列中,并且清理库存
BoxUtil
.
outFromPos
(
opTask
);
opTask
.
setOutFromPos
(
true
);
}
taskService
.
updateFinishedTask
(
opTask
);
if
(!
opTask
.
isNotifyMomo
())
{
opTask
.
setNotifyMomo
(
true
);
taskService
.
updateFinishedTask
(
opTask
);
}
if
(
OP_STATUS
.
FINISHED
.
name
().
equals
(
statusStr
))
{
//已完成,从完成缓存中清除
taskService
.
removeFinishedTask
(
opTask
);
}
}
}
else
{
opTask
.
setStatus
(
statusStr
);
//入库任务
if
(
OP_STATUS
.
FINISHED
.
name
().
equals
(
statusStr
))
{
taskService
.
moveTaskToFinished
(
opTask
);
BoxUtil
.
intoPos
(
opTask
);
ReelLockPosUtil
.
removeReelLockPosInfo
(
opTask
.
getBarcode
());
}
else
{
taskService
.
updateQueueTask
(
opTask
);
}
}
}
else
{
log
.
info
(
rfid
+
"更新状态时未找到状态:"
+
statusStr
+
""
);
}
return
ResultBean
.
newOkResult
(
""
);
}
}
src/main/java/com/neotel/smfcore/custom/aiqingzhiyin1643/finishedGoodsWarehouse/controller/PutAwayController.java
0 → 100644
查看文件 @
85cba47
package
com
.
neotel
.
smfcore
.
custom
.
aiqingzhiyin1643
.
finishedGoodsWarehouse
.
controller
;
import
com.alibaba.excel.util.StringUtils
;
import
com.neotel.smfcore.common.bean.ResultBean
;
import
com.neotel.smfcore.common.exception.ValidateException
;
import
com.neotel.smfcore.common.utils.ReelLockPosUtil
;
import
com.neotel.smfcore.common.utils.SecurityUtils
;
import
com.neotel.smfcore.core.barcode.service.po.Barcode
;
import
com.neotel.smfcore.core.barcode.utils.CodeResolve
;
import
com.neotel.smfcore.core.device.enums.OP
;
import
com.neotel.smfcore.core.device.util.DataCache
;
import
com.neotel.smfcore.core.storage.enums.CORRESPONDING_WAREHOUSE
;
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.core.system.service.po.DataLog
;
import
com.neotel.smfcore.core.system.util.TaskService
;
import
com.neotel.smfcore.custom.aiqingzhiyin1643.finishedGoodsWarehouse.bean.PutAwayLocInfo
;
import
com.neotel.smfcore.custom.aiqingzhiyin1643.finishedGoodsWarehouse.enums.PutAwayLocEnum
;
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.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
java.util.List
;
import
java.util.Map
;
@Api
(
tags
=
"上架相关"
)
@Slf4j
@RequestMapping
(
"/fgWarehouse/putAway"
)
@RestController
public
class
PutAwayController
{
@Autowired
private
IStoragePosManager
storagePosManager
;
@Autowired
private
TaskService
taskService
;
@Autowired
private
CodeResolve
codeResolve
;
@Autowired
private
DataCache
dataCache
;
@ApiOperation
(
"获取入库位置及限高信息"
)
@RequestMapping
(
"/getLocHeightLimitInfo"
)
@AnonymousAccess
public
ResultBean
getLocHeightLimitInfo
()
{
// 1. 调用枚举方法,获取封装好的「实际位置+是否限高」列表
List
<
PutAwayLocInfo
>
locInfoList
=
PutAwayLocEnum
.
getAllLocInfo
();
return
ResultBean
.
newOkResult
(
locInfoList
);
}
// 确保Controller类添加@Slf4j(无Lombok则替换为LoggerFactory)
@ApiOperation
(
"扫描码拖条码进行入库"
)
@RequestMapping
(
"/scanDragBarcodePutaway"
)
@AnonymousAccess
public
ResultBean
scanDragBarcodePutaway
(
@RequestBody
Map
<
String
,
String
>
paramMap
)
{
String
barcodeStr
=
paramMap
.
get
(
"barcode"
);
String
actualPosition
=
paramMap
.
get
(
"actualPosition"
);
String
operator
=
SecurityUtils
.
getLoginUsername
();
// 1. 基础入参(精简)
log
.
info
(
"扫码入库:条码="
+
barcodeStr
+
",实际位置="
+
actualPosition
+
",操作人="
+
operator
);
if
(
StringUtils
.
isEmpty
(
barcodeStr
))
{
log
.
warn
(
"扫码入库失败:条码为空,操作人="
+
operator
);
return
ResultBean
.
newErrorResult
(-
1
,
"smfcore.valueCanotNull"
,
"{0}不能为空"
,
new
String
[]{
"码拖条码"
});
}
// 判断成品仓配置
Storage
fgWarehouseStorage
=
null
;
for
(
Storage
storage
:
dataCache
.
getAllStorage
().
values
())
{
if
(
storage
.
getCorrespondingWarehouse
()
==
CORRESPONDING_WAREHOUSE
.
FINISHED_GOODS_WAREHOUSE
)
{
fgWarehouseStorage
=
storage
;
break
;
}
}
if
(
fgWarehouseStorage
==
null
)
{
log
.
error
(
"扫码入库失败:未配置成品仓,操作人="
+
operator
);
return
ResultBean
.
newErrorResult
(-
1
,
""
,
"请在设备管理里,配置成品仓信息"
);
}
// 2. 成品仓核心信息(仅ID/名称)
log
.
info
(
"成品仓配置:ID="
+
fgWarehouseStorage
.
getId
()
+
",名称="
+
fgWarehouseStorage
.
getName
());
// 解析条码
Barcode
barcode
=
null
;
try
{
barcode
=
codeResolve
.
resolveOneValideBarcode
(
"=2x2="
+
barcodeStr
);
// 3. 条码解析核心信息
log
.
info
(
"条码解析成功:解析后条码="
+
barcode
.
getBarcode
()
+
",料盘尺寸="
+
barcode
.
getPlateSize
()
+
",高度="
+
barcode
.
getHeight
());
}
catch
(
ValidateException
e
)
{
log
.
error
(
"条码解析失败:原始条码="
+
barcodeStr
+
",异常="
+
e
.
getMessage
());
return
ResultBean
.
newErrorResult
(-
1
,
e
.
getMsgKey
(),
e
.
getMessage
(),
e
.
getMsgParam
());
}
// 检查执行中任务
for
(
DataLog
task
:
taskService
.
getAllTasks
())
{
if
(!
task
.
isFinished
()
&&
!
task
.
isCancel
()
&&
barcode
.
getBarcode
().
equals
(
task
.
getBarcode
())
&&
fgWarehouseStorage
.
getId
().
equals
(
task
.
getStorageId
()))
{
log
.
warn
(
"扫码入库失败:条码"
+
barcode
.
getBarcode
()
+
"有执行中任务,任务ID="
+
task
.
getId
());
return
ResultBean
.
newErrorResult
(-
1
,
"smfcore.error.barcode.executing"
,
"条码[{0}}]任务正在执行"
,
new
String
[]{
barcodeStr
});
}
}
// 检查库位占用
StoragePos
oldPos
=
storagePosManager
.
getByBarcode
(
barcode
.
getBarcode
());
if
(
oldPos
!=
null
){
log
.
warn
(
"扫码入库失败:条码"
+
barcode
.
getBarcode
()
+
"已在库位"
+
oldPos
.
getPosName
());
return
ResultBean
.
newErrorResult
(-
1
,
"smfcore.materialBox.inPos"
,
"物料已在库位{0}中"
,
new
String
[]{
oldPos
.
getPosName
()});
}
// 移除锁定库位
ReelLockPosUtil
.
removeReelLockPosInfo
(
barcode
.
getBarcode
());
log
.
info
(
"移除条码"
+
barcode
.
getBarcode
()
+
"锁定库位信息"
);
// 限高+库位匹配
PutAwayLocEnum
putAwayLocEnum
=
PutAwayLocEnum
.
getByActualPosition
(
actualPosition
);
boolean
heightLimited
=
putAwayLocEnum
.
isHeightLimited
();
log
.
info
(
"限高配置:实际位置="
+
actualPosition
+
",是否限高="
+
heightLimited
);
StoragePos
pos
=
storagePosManager
.
findFgWarehouseForPutIn
(
fgWarehouseStorage
,
barcode
,
taskService
.
excludePosIds
(),
heightLimited
);
if
(
pos
==
null
){
log
.
error
(
"扫码入库失败:条码"
+
barcodeStr
+
"未找到可用库位,限高="
+
heightLimited
);
return
ResultBean
.
newErrorResult
(-
1
,
""
,
"[{0}]未找到可用的库位"
,
new
String
[]{
barcodeStr
});
}
// 4. 核心:找到的库位信息(仅ID+名称)
log
.
info
(
"找到可用库位:条码="
+
barcodeStr
+
",库位ID="
+
pos
.
getId
()
+
",库位名称="
+
pos
.
getPosName
()
+
",限高="
+
heightLimited
);
// 生成任务
DataLog
dataLog
=
new
DataLog
(
fgWarehouseStorage
,
barcode
,
pos
);
dataLog
.
setType
(
OP
.
PUT_IN
);
dataLog
.
setOperator
(
operator
);
dataLog
.
setCurrentLoc
(
putAwayLocEnum
.
name
());
taskService
.
addTaskToExecute
(
dataLog
);
// 5. 任务生成核心信息
log
.
info
(
"入库任务生成:任务ID="
+
dataLog
.
getId
()
+
",条码="
+
barcode
.
getBarcode
()
+
",入库库位="
+
pos
.
getPosName
());
return
ResultBean
.
newOkResult
(
""
);
}
}
src/main/java/com/neotel/smfcore/custom/aiqingzhiyin1643/finishedGoodsWarehouse/controller/PutOutController.java
0 → 100644
查看文件 @
85cba47
package
com
.
neotel
.
smfcore
.
custom
.
aiqingzhiyin1643
.
finishedGoodsWarehouse
.
controller
;
import
com.neotel.smfcore.common.bean.ResultBean
;
import
com.neotel.smfcore.common.utils.StringUtils
;
import
com.neotel.smfcore.core.device.util.DataCache
;
import
com.neotel.smfcore.core.system.service.po.DataLog
;
import
com.neotel.smfcore.core.system.util.TaskService
;
import
com.neotel.smfcore.custom.aiqingzhiyin1643.finishedGoodsWarehouse.bean.PutOutLocInfo
;
import
com.neotel.smfcore.custom.aiqingzhiyin1643.finishedGoodsWarehouse.util.PutOutLocInfoCache
;
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.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Comparator
;
import
java.util.List
;
import
java.util.stream.Collectors
;
@Api
(
tags
=
"下架相关"
)
@Slf4j
@RequestMapping
(
"/fgWarehouse/putOut"
)
@RestController
public
class
PutOutController
{
@Autowired
private
TaskService
taskService
;
@Autowired
private
PutOutLocInfoCache
putOutLocInfoCache
;
@ApiOperation
(
"获取所有的出库位置"
)
@RequestMapping
(
"/getAllPutOutLocInfo"
)
@AnonymousAccess
private
ResultBean
getAllPutOutLocInfo
()
{
Collection
<
PutOutLocInfo
>
putOutLocInfoList
=
putOutLocInfoCache
.
getAllPutOutLocInfo
();
putOutLocInfoList
=
putOutLocInfoList
.
stream
()
.
sorted
(
Comparator
.
comparing
(
PutOutLocInfo:
:
getName
))
.
collect
(
Collectors
.
toCollection
(
ArrayList:
:
new
));
return
ResultBean
.
newOkResult
(
putOutLocInfoList
);
}
@ApiOperation
(
"清空当前位置信息"
)
@RequestMapping
(
"/clearCurrentBindBoxInfo"
)
@AnonymousAccess
private
synchronized
ResultBean
clearCurrentBindBoxInfo
(
String
actualPosition
)
{
PutOutLocInfo
putOutLocInfo
=
putOutLocInfoCache
.
getPutOutLocInfoByActualPosition
(
actualPosition
);
if
(
putOutLocInfo
!=
null
)
{
String
currentBindBox
=
putOutLocInfo
.
getCurrentBindBox
();
if
(
StringUtils
.
isNotEmpty
(
currentBindBox
))
{
for
(
DataLog
task
:
taskService
.
getAllTasks
())
{
if
(!
task
.
isFinished
()
&&
!
task
.
isCancel
()
&&
currentBindBox
.
equals
(
task
.
getBarcode
()))
{
log
.
warn
(
"扫码入库失败:条码"
+
currentBindBox
+
"有执行中任务,任务ID="
+
task
.
getId
());
return
ResultBean
.
newErrorResult
(-
1
,
"smfcore.error.barcode.executing"
,
"条码[{0}}]任务正在执行"
,
new
String
[]{
currentBindBox
});
}
}
}
}
putOutLocInfoCache
.
removeCurrentBindBoxInfo
(
actualPosition
);
return
ResultBean
.
newOkResult
(
""
);
}
}
src/main/java/com/neotel/smfcore/custom/aiqingzhiyin1643/finishedGoodsWarehouse/enums/PutAwayLocEnum.java
0 → 100644
查看文件 @
85cba47
package
com
.
neotel
.
smfcore
.
custom
.
aiqingzhiyin1643
.
finishedGoodsWarehouse
.
enums
;
import
com.neotel.smfcore.custom.aiqingzhiyin1643.finishedGoodsWarehouse.bean.PutAwayLocInfo
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* 入库位置枚举类(PutAwayLocEnum)
* 包含位置标识、实际位置(默认与标识一致)、是否限高三个核心属性
*/
public
enum
PutAwayLocEnum
{
// 枚举项:枚举名(实际位置, 是否限高)
// 默认实际位置与枚举名一致,是否限高可根据业务需求修改(true=限高,false=不限高)
inPos1
(
"inPos1"
,
false
),
inPos2
(
"inPos2"
,
false
),
inPos3
(
"inPos3"
,
false
),
inPos4
(
"inPos4"
,
false
),
inPos5
(
"inPos5"
,
true
);
// 实际位置(默认和枚举名一致,可自定义)
private
final
String
actualPosition
;
// 是否限高(boolean类型,true=限高,false=不限高)
private
final
boolean
heightLimited
;
/**
* 枚举构造方法(必须私有,枚举构造方法不能公开)
* @param actualPosition 实际位置
* @param heightLimited 是否限高
*/
PutAwayLocEnum
(
String
actualPosition
,
boolean
heightLimited
)
{
this
.
actualPosition
=
actualPosition
;
this
.
heightLimited
=
heightLimited
;
}
// 核心方法:获取所有位置的「实际位置+是否限高」列表(返回DTO集合)
public
static
List
<
PutAwayLocInfo
>
getAllLocInfo
()
{
// 初始化DTO列表
List
<
PutAwayLocInfo
>
locInfoList
=
new
ArrayList
<>();
// 遍历所有枚举项,封装为DTO并加入列表
for
(
PutAwayLocEnum
loc
:
PutAwayLocEnum
.
values
())
{
PutAwayLocInfo
info
=
new
PutAwayLocInfo
(
loc
.
getActualPosition
(),
// 实际位置
loc
.
isHeightLimited
()
// 是否限高
);
locInfoList
.
add
(
info
);
}
return
locInfoList
;
}
// 实际位置的getter方法(枚举字段私有,通过getter访问)
public
String
getActualPosition
()
{
return
actualPosition
;
}
// 是否限高的getter方法
public
boolean
isHeightLimited
()
{
return
heightLimited
;
}
public
static
PutAwayLocEnum
getByActualPosition
(
String
actualPosition
)
{
for
(
PutAwayLocEnum
position
:
PutAwayLocEnum
.
values
())
{
if
(
position
.
getActualPosition
().
equals
(
actualPosition
))
{
return
position
;
}
}
return
null
;
}
public
static
PutAwayLocEnum
getByEnumName
(
String
enumName
)
{
for
(
PutAwayLocEnum
position
:
PutAwayLocEnum
.
values
())
{
if
(
position
.
name
().
equals
(
enumName
))
{
return
position
;
}
}
return
null
;
}
}
\ No newline at end of file
src/main/java/com/neotel/smfcore/custom/aiqingzhiyin1643/finishedGoodsWarehouse/enums/PutOutLocEnum.java
0 → 100644
查看文件 @
85cba47
package
com
.
neotel
.
smfcore
.
custom
.
aiqingzhiyin1643
.
finishedGoodsWarehouse
.
enums
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* 出库位置枚举类(PutOutLocEnum)
* 仅包含出库位置标识、实际位置(默认与标识一致)核心属性
*/
public
enum
PutOutLocEnum
{
outPos1
(
"outPos1"
),
outPos2
(
"outPos2"
),
outPos3
(
"outPos3"
),
outPos4
(
"outPos4"
),
outPos5
(
"outPos5"
),
outPos6
(
"outPos6"
),
outPos7
(
"outPos7"
);
// 仅保留:实际位置(默认和枚举名一致,可自定义)
private
final
String
actualPosition
;
/**
* 枚举构造方法(仅初始化实际位置)
* @param actualPosition 实际位置
*/
PutOutLocEnum
(
String
actualPosition
)
{
this
.
actualPosition
=
actualPosition
;
}
// 获取实际位置
public
String
getActualPosition
()
{
return
actualPosition
;
}
/**
* 根据实际位置返回对应的枚举值(核心查询方法保留)
* @param actualPosition 实际位置(如outPos2)
* @return 匹配的枚举实例
* @throws IllegalArgumentException 入参为空/无匹配项时抛异常
*/
public
static
PutOutLocEnum
getByActualPosition
(
String
actualPosition
)
{
for
(
PutOutLocEnum
loc
:
PutOutLocEnum
.
values
())
{
if
(
actualPosition
.
equals
(
loc
.
getActualPosition
()))
{
return
loc
;
}
}
return
null
;
}
/**
* 获取所有出库位置的实际位置列表(移除限高,仅返回位置)
* @return 所有实际位置字符串列表
*/
public
static
List
<
String
>
getAllActualPositions
()
{
List
<
String
>
locList
=
new
ArrayList
<>();
for
(
PutOutLocEnum
loc
:
PutOutLocEnum
.
values
())
{
locList
.
add
(
loc
.
getActualPosition
());
}
return
locList
;
}
public
static
List
<
PutOutLocEnum
>
getAllPutOutLoc
()
{
List
<
PutOutLocEnum
>
locList
=
new
ArrayList
<>();
for
(
PutOutLocEnum
loc
:
PutOutLocEnum
.
values
())
{
locList
.
add
(
loc
);
}
return
locList
;
}
}
src/main/java/com/neotel/smfcore/custom/aiqingzhiyin1643/finishedGoodsWarehouse/util/PutOutLocInfoCache.java
0 → 100644
查看文件 @
85cba47
package
com
.
neotel
.
smfcore
.
custom
.
aiqingzhiyin1643
.
finishedGoodsWarehouse
.
util
;
import
com.neotel.smfcore.common.utils.Constants
;
import
com.neotel.smfcore.common.utils.StringUtils
;
import
com.neotel.smfcore.core.device.util.DataCache
;
import
com.neotel.smfcore.custom.aiqingzhiyin1643.finishedGoodsWarehouse.bean.PutOutLocInfo
;
import
com.neotel.smfcore.custom.aiqingzhiyin1643.finishedGoodsWarehouse.enums.PutOutLocEnum
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.PostConstruct
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
@Component
public
class
PutOutLocInfoCache
{
@Autowired
private
DataCache
dataCache
;
@PostConstruct
private
void
init
()
{
Map
<
String
,
PutOutLocInfo
>
cacheMap
=
dataCache
.
getCache
(
Constants
.
Cache_PutOutLoc_Info
);
if
(
cacheMap
==
null
)
{
cacheMap
=
new
HashMap
<>();
}
List
<
PutOutLocEnum
>
putOutLocEnumList
=
PutOutLocEnum
.
getAllPutOutLoc
();
for
(
PutOutLocEnum
put
:
putOutLocEnumList
)
{
if
(
cacheMap
.
get
(
put
.
name
())
==
null
)
{
cacheMap
.
put
(
put
.
name
(),
new
PutOutLocInfo
(
put
.
name
(),
put
.
getActualPosition
(),
""
));
}
}
dataCache
.
updateCache
(
Constants
.
Cache_PutOutLoc_Info
,
cacheMap
);
}
public
Collection
<
PutOutLocInfo
>
getAllPutOutLocInfo
()
{
Map
<
String
,
PutOutLocInfo
>
cacheMap
=
dataCache
.
getCache
(
Constants
.
Cache_PutOutLoc_Info
);
if
(
cacheMap
==
null
){
cacheMap
=
new
HashMap
<>();
}
return
cacheMap
.
values
();
}
public
String
bindCurrentBox
(
String
box
)
{
Map
<
String
,
PutOutLocInfo
>
cacheMap
=
dataCache
.
getCache
(
Constants
.
Cache_PutOutLoc_Info
);
if
(
cacheMap
==
null
)
{
cacheMap
=
new
HashMap
<>();
}
boolean
bindBox
=
false
;
String
result
=
""
;
for
(
String
name
:
cacheMap
.
keySet
())
{
PutOutLocInfo
putOutLocInfo
=
cacheMap
.
get
(
name
);
if
(
StringUtils
.
isEmpty
(
putOutLocInfo
.
getCurrentBindBox
()))
{
putOutLocInfo
.
setCurrentBindBox
(
box
);
result
=
putOutLocInfo
.
getName
();
bindBox
=
true
;
break
;
}
else
{
if
(
box
.
equals
(
putOutLocInfo
.
getCurrentBindBox
())){
result
=
putOutLocInfo
.
getName
();
break
;
}
}
}
if
(
bindBox
)
{
dataCache
.
updateCache
(
Constants
.
Cache_PutOutLoc_Info
,
cacheMap
);
}
return
result
;
}
public
void
removeCurrentBindBoxInfo
(
String
actualPosition
)
{
Map
<
String
,
PutOutLocInfo
>
cacheMap
=
dataCache
.
getCache
(
Constants
.
Cache_PutOutLoc_Info
);
if
(
cacheMap
==
null
)
{
cacheMap
=
new
HashMap
<>();
}
PutOutLocEnum
putOutLocEnum
=
PutOutLocEnum
.
getByActualPosition
(
actualPosition
);
if
(
putOutLocEnum
!=
null
){
PutOutLocInfo
putOutLocInfo
=
cacheMap
.
get
(
putOutLocEnum
.
name
());
if
(
putOutLocInfo
==
null
){
putOutLocInfo
=
new
PutOutLocInfo
(
putOutLocEnum
.
name
(),
putOutLocEnum
.
getActualPosition
(),
""
);
}
putOutLocInfo
.
setCurrentBindBox
(
""
);
cacheMap
.
put
(
putOutLocEnum
.
name
(),
putOutLocInfo
);
}
dataCache
.
updateCache
(
Constants
.
Cache_PutOutLoc_Info
,
cacheMap
);
}
public
PutOutLocInfo
getPutOutLocInfoByActualPosition
(
String
actualPosition
)
{
Map
<
String
,
PutOutLocInfo
>
cacheMap
=
dataCache
.
getCache
(
Constants
.
Cache_PutOutLoc_Info
);
if
(
cacheMap
==
null
)
{
cacheMap
=
new
HashMap
<>();
}
PutOutLocEnum
putOutLocEnum
=
PutOutLocEnum
.
getByActualPosition
(
actualPosition
);
if
(
putOutLocEnum
!=
null
){
PutOutLocInfo
putOutLocInfo
=
cacheMap
.
get
(
putOutLocEnum
.
name
());
if
(
putOutLocInfo
==
null
){
putOutLocInfo
=
new
PutOutLocInfo
(
putOutLocEnum
.
name
(),
putOutLocEnum
.
getActualPosition
(),
""
);
}
return
putOutLocInfo
;
}
return
null
;
}
}
编写
预览
支持
Markdown
格式
附加文件
你添加了
0
人
到此讨论。请谨慎行事。
Finish editing this message first!
Cancel
请
注册
或
登录
后发表评论