Skip to content
切换导航条
切换导航条
当前项目
正在载入...
登录
孙克
/
smf-core
转到一个项目
切换导航栏
切换导航栏固定状态
项目
群组
代码片段
帮助
项目
活动
版本库
流水线
图表
问题
0
合并请求
0
维基
网络
创建新的问题
作业
提交
问题看板
文件
提交
网络
比较
分支
标签
Commit 098c4760
由
zshaohui
编写于
2024-06-28 12:14:59 +0800
浏览文件
选项
浏览文件
标签
下载
电子邮件补丁
差异文件
odn出库 必须满足数量 才能出库
1 个父辈
b05b1c45
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
142 行增加
和
39 行删除
src/main/java/com/neotel/smfcore/core/order/LiteOrderCache.java
src/main/java/com/neotel/smfcore/core/order/util/CombinationUtil.java
src/main/java/com/neotel/smfcore/custom/luxsan/api/LuxsanApi.java
src/main/java/com/neotel/smfcore/core/order/LiteOrderCache.java
查看文件 @
098c476
...
@@ -23,6 +23,7 @@ import com.neotel.smfcore.core.order.service.manager.ILiteOrderItemManager;
...
@@ -23,6 +23,7 @@ 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.order.util.CombinationUtil
;
import
com.neotel.smfcore.core.storage.bean.InventoryItem
;
import
com.neotel.smfcore.core.storage.bean.InventoryItem
;
import
com.neotel.smfcore.core.storage.enums.CHECKOUT_TYPE
;
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
;
...
@@ -1381,46 +1382,68 @@ public class LiteOrderCache {
...
@@ -1381,46 +1382,68 @@ public class LiteOrderCache {
for
(
LiteOrderItem
orderItem
:
cacheOrder
.
getOrderItems
())
{
for
(
LiteOrderItem
orderItem
:
cacheOrder
.
getOrderItems
())
{
String
partNumber
=
orderItem
.
getPn
();
int
taskNum
=
0
;
int
remainNum
=
orderItem
.
getNeedNum
()
-
orderItem
.
getTotalOutNum
();
int
remainNum
=
orderItem
.
getNeedNum
()
-
orderItem
.
getTotalOutNum
();
//1.查找所有符合条件的pn
if
(
remainNum
<=
0
)
{
while
(
taskNum
<
remainNum
)
{
continue
;
}
log
.
info
(
orderNo
+
"已分配数量为:"
+
taskNum
+
",剩余数量为:"
+
remainNum
);
Collection
<
String
>
excludePosIds
=
excludeOutPosIds
();
Collection
<
String
>
excludePosIds
=
excludeOutPosIds
();
if
(
dataLogList
!=
null
&&
!
dataLogList
.
isEmpty
()){
//找到hold的
List
<
String
>
holdPosIdList
=
getHoldPosIdList
(
cacheOrder
);
if
(
holdPosIdList
!=
null
&&
!
holdPosIdList
.
isEmpty
())
{
excludePosIds
.
addAll
(
holdPosIdList
);
}
if
(
dataLogList
!=
null
&&
!
dataLogList
.
isEmpty
())
{
for
(
DataLog
dataLog
:
dataLogList
)
{
for
(
DataLog
dataLog
:
dataLogList
)
{
excludePosIds
.
add
(
dataLog
.
getPosId
());
excludePosIds
.
add
(
dataLog
.
getPosId
());
}
}
}
}
//1.先从执行的料箱中出库
StoragePos
pos
=
null
;
String
pn
=
orderItem
.
getPn
();
if
(
storagePosList
!=
null
&&
!
storagePosList
.
isEmpty
())
{
String
warehouseCode
=
orderItem
.
getWarehouseCode
();
for
(
StoragePos
storagePos
:
storagePosList
)
{
if
(
excludePosIds
.
contains
(
storagePos
.
getId
()))
{
Criteria
c
=
Criteria
.
where
(
"barcode.partNumber"
).
is
(
pn
)
continue
;
.
and
(
"id"
).
nin
(
excludePosIds
)
}
.
and
(
"enabled"
).
is
(
true
)
if
(
partNumber
.
equals
(
storagePos
.
getBarcode
().
getPartNumber
()))
{
.
and
(
"storageId"
).
in
(
storageIdList
)
pos
=
storagePos
;
.
and
(
"barcode.warehouseCode"
).
is
(
warehouseCode
);
break
;
List
<
StoragePos
>
posList
=
storagePosManager
.
findByQuery
(
new
Query
(
c
));
if
(
posList
==
null
||
posList
.
isEmpty
())
{
finishedOrderTasks
(
cacheOrder
);
throw
new
ValidateException
(
""
,
orderItem
.
getPn
()
+
"库存不足,odn:"
+
cacheOrder
.
getOrderNo
()
+
"无法进行出库"
);
}
}
//开始寻找组合数量为needOutNum的库存
List
<
Integer
>
amountList
=
new
ArrayList
<>();
for
(
StoragePos
storagePos
:
posList
)
{
Barcode
barcode
=
storagePos
.
getBarcode
();
amountList
.
add
(
barcode
.
getQty
());
}
}
//寻找到组合
List
<
List
<
Integer
>>
combinations
=
CombinationUtil
.
findCombinationsWithoutDuplicates
(
amountList
,
remainNum
);
Collections
.
sort
(
combinations
,
Comparator
.
comparingInt
(
List:
:
size
));
if
(
combinations
.
isEmpty
())
{
finishedOrderTasks
(
cacheOrder
);
throw
new
ValidateException
(
""
,
orderItem
.
getPn
()
+
"需要出库的数量为:"
+
remainNum
+
",未找到符合条件的组合"
);
}
}
if
(
pos
==
null
)
{
//开始出库
pos
=
storagePosManager
.
findPartNumberInStorages
(
storageIdList
,
partNumber
,
excludePosIds
,
checkoutType
,
orderItem
.
getBrand
(),
orderItem
.
getWarehouseCode
());
List
<
Integer
>
needOutNumList
=
combinations
.
get
(
0
);
while
(
needOutNumList
.
size
()
>
0
)
{
Integer
qty
=
needOutNumList
.
get
(
0
);
for
(
StoragePos
pos
:
posList
)
{
if
(
excludePosIds
.
contains
(
pos
.
getId
()))
{
continue
;
}
}
if
(
pos
==
null
)
{
break
;
}
else
{
Barcode
barcode
=
pos
.
getBarcode
();
Barcode
barcode
=
pos
.
getBarcode
();
log
.
info
(
barcode
.
getBarcode
()
+
"需要生成出库任务,工单号为:"
+
orderNo
+
",数量为:"
+
barcode
.
getQty
());
if
(
barcode
.
getQty
()
==
qty
)
{
taskNum
=
taskNum
+
barcode
.
getQty
(
);
log
.
info
(
barcode
.
getBarcode
()
+
"需要生成出库任务,工单号为:"
+
orderNo
+
",数量为:"
+
barcode
.
getQty
()
);
taskReelCount
=
taskReelCount
+
1
;
taskReelCount
=
taskReelCount
+
1
;
DataLog
task
=
newTask
(
pos
);
DataLog
task
=
newTask
(
pos
);
task
.
setSourceId
(
cacheOrder
.
getId
());
task
.
setSourceId
(
cacheOrder
.
getId
());
...
@@ -1430,23 +1453,17 @@ public class LiteOrderCache {
...
@@ -1430,23 +1453,17 @@ public class LiteOrderCache {
task
.
setType
(
OP
.
CHECKOUT
);
task
.
setType
(
OP
.
CHECKOUT
);
task
.
setStatus
(
OP_STATUS
.
WAIT
.
name
());
task
.
setStatus
(
OP_STATUS
.
WAIT
.
name
());
task
.
setLoc
(
TaskLocUtil
.
OUT
);
task
.
setLoc
(
TaskLocUtil
.
OUT
);
if
(
StringUtils
.
isNotEmpty
(
barcode
.
getCartonId
()))
{
if
(
StringUtils
.
isNotEmpty
(
barcode
.
getCartonId
()))
{
task
.
setCartonId
(
barcode
.
getCartonId
());
task
.
setCartonId
(
barcode
.
getCartonId
());
}
}
task
.
setOdn
(
true
);
task
.
setOdn
(
true
);
dataLogList
.
add
(
task
);
dataLogList
.
add
(
task
);
excludePosIds
.
add
(
pos
.
getId
());
break
;
}
}
}
}
needOutNumList
.
remove
(
0
);
//如果数量不满足,则提示出来
if
(
taskNum
<
remainNum
){
finishedOrderTasks
(
cacheOrder
);
throw
new
ValidateException
(
""
,
orderItem
.
getPn
()+
"库存不足,odn:"
+
cacheOrder
.
getOrderNo
()+
"无法进行出库"
);
}
}
}
for
(
DataLog
dataLog
:
dataLogList
)
{
taskService
.
addTaskToExecute
(
dataLog
);
}
}
if
(
taskReelCount
<=
0
)
{
if
(
taskReelCount
<=
0
)
{
...
@@ -1455,6 +1472,9 @@ public class LiteOrderCache {
...
@@ -1455,6 +1472,9 @@ public class LiteOrderCache {
throw
new
ValidateException
(
"smfcore.order.out.noTask"
,
"工单无可执行的任务"
);
throw
new
ValidateException
(
"smfcore.order.out.noTask"
,
"工单无可执行的任务"
);
}
}
for
(
DataLog
dataLog
:
dataLogList
)
{
taskService
.
addTaskToExecute
(
dataLog
);
}
cacheOrder
.
setTaskReelCount
(
taskReelCount
);
cacheOrder
.
setTaskReelCount
(
taskReelCount
);
...
@@ -1463,4 +1483,28 @@ public class LiteOrderCache {
...
@@ -1463,4 +1483,28 @@ public class LiteOrderCache {
log
.
info
(
"生成工单"
+
orderNo
+
"任务结束,数量为:"
+
taskReelCount
);
log
.
info
(
"生成工单"
+
orderNo
+
"任务结束,数量为:"
+
taskReelCount
);
}
}
private
List
<
String
>
getHoldPosIdList
(
LiteOrder
cacheOrder
)
{
//如果是hold的,判断有没有符合的条件
List
<
String
>
holdPosIdList
=
new
ArrayList
<>();
for
(
LiteOrderItem
orderItem
:
cacheOrder
.
getOrderItems
())
{
List
<
FetchHoldInfoResult
>
resultList
=
LuxsanApi
.
fetchHoldInfo
(
new
FetchHoldInfoRequest
(
CommonUtil
.
plantCode
,
orderItem
.
getSrcWarehouse
(),
orderItem
.
getPn
()));
if
(
resultList
!=
null
&&
!
resultList
.
isEmpty
())
{
List
<
String
>
palletIdList
=
resultList
.
stream
().
map
(
FetchHoldInfoResult:
:
getPALLET_ID
).
collect
(
Collectors
.
toList
());
List
<
Criteria
>
orCriterialList
=
Lists
.
newArrayList
();
orCriterialList
.
add
(
Criteria
.
where
(
"barcode.barcode"
).
in
(
palletIdList
));
orCriterialList
.
add
(
Criteria
.
where
(
"barcode.palletId"
).
in
(
palletIdList
));
Criteria
c
=
new
Criteria
().
orOperator
(
orCriterialList
);
List
<
StoragePos
>
posList
=
storagePosManager
.
findByQuery
(
new
Query
(
c
));
if
(
posList
!=
null
&&
!
posList
.
isEmpty
())
{
for
(
StoragePos
pos
:
posList
)
{
holdPosIdList
.
add
(
pos
.
getId
());
}
}
}
}
return
holdPosIdList
;
}
}
}
src/main/java/com/neotel/smfcore/core/order/util/CombinationUtil.java
0 → 100644
查看文件 @
098c476
package
com
.
neotel
.
smfcore
.
core
.
order
.
util
;
import
java.util.ArrayList
;
import
java.util.List
;
public
class
CombinationUtil
{
private
static
void
backtrack
(
List
<
Integer
>
numbers
,
int
targetSum
,
int
start
,
List
<
Integer
>
current
,
List
<
List
<
Integer
>>
combinations
,
boolean
used
[])
{
if
(
targetSum
==
0
)
{
combinations
.
add
(
new
ArrayList
<>(
current
));
return
;
}
if
(
targetSum
<
0
||
start
>=
numbers
.
size
())
{
return
;
}
for
(
int
i
=
start
;
i
<
numbers
.
size
();
i
++)
{
// 如果不允许重复使用数字,并且当前数字已经被使用过,则跳过
if
(
used
!=
null
&&
used
[
i
])
{
continue
;
}
// 选择当前数字
current
.
add
(
numbers
.
get
(
i
));
// 如果不允许重复使用数字,则标记当前数字为已使用
if
(
used
!=
null
)
{
used
[
i
]
=
true
;
}
// 递归调用,继续查找剩余的数字
backtrack
(
numbers
,
targetSum
-
numbers
.
get
(
i
),
i
+
1
,
current
,
combinations
,
used
);
// 回溯,移除当前选择的数字
current
.
remove
(
current
.
size
()
-
1
);
// 如果不允许重复使用数字,则取消标记
if
(
used
!=
null
)
{
used
[
i
]
=
false
;
}
}
}
// 如果不允许重复使用数字,可以使用以下版本的findCombinations方法
public
static
List
<
List
<
Integer
>>
findCombinationsWithoutDuplicates
(
List
<
Integer
>
numbers
,
int
targetSum
)
{
boolean
[]
used
=
new
boolean
[
numbers
.
size
()];
return
findCombinations
(
numbers
,
targetSum
,
used
);
}
// 带有used数组的findCombinations方法
private
static
List
<
List
<
Integer
>>
findCombinations
(
List
<
Integer
>
numbers
,
int
targetSum
,
boolean
[]
used
)
{
List
<
List
<
Integer
>>
combinations
=
new
ArrayList
<>();
backtrack
(
numbers
,
targetSum
,
0
,
new
ArrayList
<>(),
combinations
,
used
);
return
combinations
;
}
}
src/main/java/com/neotel/smfcore/custom/luxsan/api/LuxsanApi.java
查看文件 @
098c476
...
@@ -726,7 +726,8 @@ public class LuxsanApi extends DefaultSmfApiListener {
...
@@ -726,7 +726,8 @@ public class LuxsanApi extends DefaultSmfApiListener {
LuxsanApiResult
apiResult
=
JSONObject
.
parseObject
(
resultStr
,
LuxsanApiResult
.
class
);
LuxsanApiResult
apiResult
=
JSONObject
.
parseObject
(
resultStr
,
LuxsanApiResult
.
class
);
if
(
LuxsanApiEnum
.
ERROR
.
equals
(
apiResult
.
getMSGTY
()))
{
if
(
LuxsanApiEnum
.
ERROR
.
equals
(
apiResult
.
getMSGTY
()))
{
throw
new
ValidateException
(
"smfcore.api.error"
,
"接口请求失败[{0}]"
,
new
String
[]{
apiResult
.
getMSGTX
()});
//throw new ValidateException("smfcore.api.error", "接口请求失败[{0}]", new String[]{apiResult.getMSGTX()});
return
new
ArrayList
<>();
}
}
List
<
FetchHoldInfoResult
>
resultList
=
JSONObject
.
parseArray
(
apiResult
.
getDATA
(),
FetchHoldInfoResult
.
class
);
List
<
FetchHoldInfoResult
>
resultList
=
JSONObject
.
parseArray
(
apiResult
.
getDATA
(),
FetchHoldInfoResult
.
class
);
...
@@ -736,9 +737,10 @@ public class LuxsanApi extends DefaultSmfApiListener {
...
@@ -736,9 +737,10 @@ public class LuxsanApi extends DefaultSmfApiListener {
}
catch
(
ApiException
e
)
{
}
catch
(
ApiException
e
)
{
log
.
error
(
"fetchHoldInfo请求失败:"
+
e
.
getMessage
());
log
.
error
(
"fetchHoldInfo请求失败:"
+
e
.
getMessage
());
throw
new
ValidateException
(
"smfcore.api.error"
,
"接口请求失败[{0}]"
,
new
String
[]{
e
.
getMessage
()});
//throw new ValidateException("smfcore.api.error", "接口请求失败[{0}]", new String[]{e.getMessage()});
return
new
ArrayList
<>();
}
}
throw
new
ValidateException
(
"smfcore.api.error"
,
"接口请求失败[{0}]"
,
new
String
[]{
"未找到对应的获取不可用(HOLD)库存信息"
}
);
return
new
ArrayList
<>(
);
}
}
...
...
编写
预览
支持
Markdown
格式
附加文件
你添加了
0
人
到此讨论。请谨慎行事。
Finish editing this message first!
Cancel
请
注册
或
登录
后发表评论