rev:修改出库规则,fifo必须为第一个出库规则;opt:托盘出入库添加校验;手持组盘功能添加可以库位校验

This commit is contained in:
zhangzq
2024-07-18 14:00:19 +08:00
parent 28d3b53acb
commit 8dd2ea5d0c
11 changed files with 109 additions and 54 deletions

View File

@@ -45,7 +45,7 @@ public class AppRun implements CommandLineRunner {
@Override
public void run(String... args) {
HeartClientServer heartServer = new HeartClientServer(new InetSocketAddress("192.168.10.48", 20889));
// HeartClientServer heartServer = new HeartClientServer(new InetSocketAddress("192.168.10.60", 20889));
System.out.println("--------项目启动完成--------");
}

View File

@@ -12,5 +12,6 @@ public class DictConstantPool {
public static final String DICT_SYS_CODE = "system_type";
public static final String DICT_SYS_NAME = "所属系统";
public static final int STRUCT_COUNT = 5;
public static final Map<String,String> PRODUCT_OUT_POINT = MapOf.of("A1","1101","A2","2114","A3","3204");
}

View File

@@ -14,6 +14,7 @@ import org.nl.wms.base_manage.vehicle.service.dao.BmVehicleInfo;
public class VehicleQuery extends BaseQuery<BmVehicleInfo> {
private String vehicle_code_begin;
private String vehicle_code;
private String vehicle_code_end;
private String vehicle_type;

View File

@@ -45,7 +45,7 @@ public class StartDecisionChainer extends DecisionerChain<List> {
@Override
protected List execute(List from) {
List list;
List list = new ArrayList();
boolean in_storage = StatusEnum.STRATEGY_TYPE.code("入库").equals(strategy_type);
IStIvtStructattrService iStIvtStructattrService = SpringContextHolder.getBean(IStIvtStructattrService.class);
if (in_storage){
@@ -56,6 +56,7 @@ public class StartDecisionChainer extends DecisionerChain<List> {
query.isNull("vehicle_code");
list = iStIvtStructattrService.list(query);
}else {
//出库流程由于有货货位较多会生成多个对象容易内存益出在fifo中直接通过materilal过滤目标
list = iStIvtStructattrService.structVehicle(MapOf.of("stor_code",startParam.getString("stor_code")));
}
return list;

View File

@@ -46,9 +46,10 @@ public class FIFORuleHandler extends Decisioner<StructattrVechielDto, JSONObject
@Override
public List<StructattrVechielDto> handler(List<StructattrVechielDto> list, JSONObject param) {
// 判断仓位是否为空
if (ObjectUtil.isEmpty(list)) {
throw new BadRequestException("库存分配失败:库存不足!");
}
// if (ObjectUtil.isEmpty(list)) {
// throw new BadRequestException("库存分配失败:库存不足!");
// }
// List<String> need = list.stream().map(StructattrVechielDto::getVehicle_code).collect(Collectors.toList());
//分配数量
int plan_qty = param.getInteger("qty");
//当前条件只有id批次
@@ -56,15 +57,17 @@ public class FIFORuleHandler extends Decisioner<StructattrVechielDto, JSONObject
, "pcsn", param.getString("pcsn")
, "stor_code", param.getString("stor_code")
, "plan_qty", plan_qty
, "is_lock", "false"
, "order_by", "ABS(qty-#{plan_qty}) asc,update_time asc")
);
int finalPlan_qty = plan_qty;
int finalPlan_qty = 0;
// vechielDtos.sort(Comparator.comparingInt(o -> (o.getQty().intValue() - finalPlan_qty)));
List<String> need = list.stream().map(StructattrVechielDto::getVehicle_code).collect(Collectors.toList());
List<StructattrVechielDto> disList = new ArrayList<>();
for (StructattrVechielDto structattr : vechielDtos) {
if (need.contains(structattr.getVehicle_code()) && structattr.getFrozen_qty().intValue()==0){
// if (need.contains(structattr.getVehicle_code()) && structattr.getFrozen_qty().intValue()==0){
if (structattr.getFrozen_qty().intValue()==0){
int cause_qty = structattr.getQty().subtract(structattr.getFrozen_qty()).intValue();
int sub = plan_qty - cause_qty;
disList.add(structattr);
@@ -74,8 +77,12 @@ public class FIFORuleHandler extends Decisioner<StructattrVechielDto, JSONObject
}
structattr.setFrozen_qty(new BigDecimal(cause_qty));
plan_qty = sub;
finalPlan_qty = sub;
}
}
if (finalPlan_qty>0){
throw new BadRequestException("库存不足:物料"+param.getString("material_id")+"当前库存可用数"+(param.getInteger("qty").intValue()-finalPlan_qty));
}
return disList;
}
}

View File

@@ -8,13 +8,11 @@ import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.StringUtils;
import org.nl.common.TableDataInfo;
import org.nl.common.domain.constant.DictConstantPool;
import org.nl.common.domain.entity.PageQuery;
import org.nl.common.domain.exception.BadRequestException;
import org.nl.common.enums.StatusEnum;
import org.nl.common.utils.CodeUtil;
import org.nl.common.utils.IdUtil;
import org.nl.common.utils.MapOf;
import org.nl.common.utils.SecurityUtils;
import org.nl.common.utils.*;
import org.nl.wms.base_manage.vehicle.service.IBmVehicleInfoService;
import org.nl.wms.base_manage.vehicle.service.dao.BmVehicleInfo;
import org.nl.wms.md_manage.vehicleMater.service.IMdPbVehicleMaterService;
@@ -26,6 +24,8 @@ import org.nl.wms.md_manage.group_dick.service.IMdGruopDickService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.nl.wms.md_manage.group_dick.service.dto.GroupDickQuery;
import org.nl.wms.md_manage.vehicleMater.service.dto.MdPbVehicleMaterVo;
import org.nl.wms.stor_manage.struct.service.IStIvtStructattrService;
import org.nl.wms.stor_manage.struct.service.dao.StIvtStructattr;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -58,6 +58,8 @@ public class MdGruopDickServiceImpl extends ServiceImpl<MdGruopDickMapper, MdGru
@Autowired
private IBmVehicleInfoService iBmVehicleInfoService;
@Autowired
private IStIvtStructattrService iStIvtStructattrService;
@Override
public Object queryAll(GroupDickQuery query, PageQuery pageQuery) {
@@ -73,6 +75,19 @@ public class MdGruopDickServiceImpl extends ServiceImpl<MdGruopDickMapper, MdGru
@Override
@Transactional
public void groupDick(JSONObject forms) {
RedissonUtils.lock(()->{
QueryWrapper<StIvtStructattr> query = new QueryWrapper<StIvtStructattr>()
.eq("is_used", true)
.eq("lock_type", StatusEnum.LOCK.code("无锁"))
.eq("stor_code", forms.getString("stor_code"))
.isNull("vehicle_code");;
int structCount = iStIvtStructattrService.count(query);
if (structCount< DictConstantPool.STRUCT_COUNT){
throw new BadRequestException("入库失败:当前仓库可用库位小于"+DictConstantPool.STRUCT_COUNT);
}
}, StatusEnum.STRATEGY_TYPE.code("入库")+forms.getString("stor_code"),5);
List<JSONObject> tableData = (ArrayList)forms.remove("item");
String now = DateUtil.now();
forms.put("create_name",SecurityUtils.getCurrentNickName());

View File

@@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.nl.common.TableDataInfo;
import org.nl.common.anno.Log;
import org.nl.common.domain.entity.PageQuery;
@@ -53,15 +54,19 @@ public class MdPbVehicleMaterController {
public ResponseEntity<Object> getMaterialByVehicle(@PathVariable String vehicle_code) {
LambdaQueryWrapper<MdPbVehicleMater> lqw = new LambdaQueryWrapper<>();
lqw.eq(MdPbVehicleMater::getVehicle_code, vehicle_code);
lqw.eq(MdPbVehicleMater::getIs_delete,false);
MdPbVehicleMater one = iMdPbVehicleMaterService.getOne(lqw);
JSONObject res = new JSONObject();
res.put("vehicle_code", vehicle_code);
if (ObjectUtil.isNotEmpty(one)) {
MdMeMaterialbase materialbase = materialbaseService.getById(one.getMaterial_id());
res.put("material_id", one.getMaterial_id());
res.put("id", one.getId());
res.put("pcsn", one.getPcsn());
res.put("material_code", materialbase.getMaterial_code());
res.put("storage_qty", one.getQty());
res.put("qty", one.getQty());
res.put("frozen_qty", one.getFrozen_qty());
res.put("proc_inst_id", one.getProc_inst_id());
res.put("material_spec", materialbase.getMaterial_spec());
}
return new ResponseEntity<>(res, HttpStatus.OK);
@@ -85,21 +90,21 @@ public class MdPbVehicleMaterController {
@PostMapping("/updateVehicleMaterial")
public ResponseEntity<Object> updateVehicleMaterial(@RequestBody JSONObject req) {
String vehicle_code = req.getString("vehicle_code");
Assert.notBlank(vehicle_code);
LambdaQueryWrapper<MdPbVehicleMater> lqw = new LambdaQueryWrapper<>();
lqw.eq(MdPbVehicleMater::getVehicle_code, vehicle_code);
MdPbVehicleMater one = iMdPbVehicleMaterService.getOne(lqw);
if (ObjectUtil.isEmpty(one)) {
throw new BadRequestException("载具物料表中不存在该载具信息!");
if (StringUtils.isNotEmpty((req.getString("id")))){
if (StringUtils.isEmpty(req.getString("material_id"))){
throw new BadRequestException("载具物料不能为空");
}else {
MdPbVehicleMater mater = new MdPbVehicleMater();
mater.setId(req.getString("id"));
mater.setMaterial_id(req.getString("material_id"));
mater.setPcsn(req.getString("pcsn"));
mater.setQty(req.getBigDecimal("qty"));
mater.setFrozen_qty(req.getBigDecimal("frozen_qty"));
mater.setPcsn(req.getString("pcsn"));
mater.setProc_inst_id(req.getString("proc_inst_id"));
iMdPbVehicleMaterService.updateById(mater);
}
}
MdMeMaterialbase materialbase = materialbaseService.getOne(new LambdaQueryWrapper<MdMeMaterialbase>().eq(MdMeMaterialbase::getMaterial_code, req.getString("material_code")));
MdPbVehicleMater mater = new MdPbVehicleMater();
mater.setId(one.getId());
mater.setMaterial_id(materialbase.getMaterial_id());
mater.setPcsn(req.getString("pcsn"));
mater.setQty(req.getBigDecimal("storage_qty"));
iMdPbVehicleMaterService.updateById(mater);
return new ResponseEntity<>(HttpStatus.OK);
}

View File

@@ -5,6 +5,7 @@ import cn.dev33.satoken.annotation.SaIgnore;
import com.alibaba.fastjson.JSONObject;
import org.nl.common.TableDataInfo;
import org.nl.common.anno.Log;
import org.nl.wms.md_manage.group_dick.service.IMdGruopDickService;
import org.nl.wms.pda_manage.palletio.service.PalletIostorinvService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
@@ -27,23 +28,15 @@ import org.springframework.web.bind.annotation.RestController;
public class GroupController {
@Autowired
private PalletIostorinvService palletIostorinvService;
private IMdGruopDickService iMdGruopDickService;
@PostMapping("in")
@SaIgnore
@Log("手持托盘入库")
@Log("手持组盘操作")
public ResponseEntity<Object> inStorage(@RequestBody JSONObject form) {
palletIostorinvService.inStorage(form);
iMdGruopDickService.groupDick(form);
return new ResponseEntity<>(TableDataInfo.build(),HttpStatus.OK);
}
@PostMapping("out")
@SaIgnore
@Log("手持托盘出库")
public ResponseEntity<Object> outStorage(@RequestBody JSONObject form) {
palletIostorinvService.outStorage(form);
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@@ -5,17 +5,25 @@ import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.nl.common.domain.constant.DictConstantPool;
import org.nl.common.domain.exception.BadRequestException;
import org.nl.common.enums.StatusEnum;
import org.nl.common.publish.BussEventMulticaster;
import org.nl.common.utils.*;
import org.nl.wms.flow_manage.flow.framework.process.nodeType.excess.impl.DecisionHandler;
import org.nl.wms.flow_manage.monitor.event.FlowStartEvent;
import org.nl.wms.md_manage.group_dick.service.dao.MdGruopDick;
import org.nl.wms.md_manage.vehicleMater.service.IMdPbVehicleMaterService;
import org.nl.wms.md_manage.vehicleMater.service.dao.MdPbVehicleMater;
import org.nl.wms.stor_manage.struct.service.IStIvtStructattrService;
import org.nl.wms.stor_manage.struct.service.dao.StIvtStructattr;
import org.nl.wms.stor_manage.struct.service.dto.StructattrVechielDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/*
* @author ZZQ
@@ -26,6 +34,8 @@ public class PalletIostorinvService {
@Autowired
private IMdPbVehicleMaterService iMdPbVehicleMaterService;
@Autowired
private IStIvtStructattrService iStIvtStructattrService;
//托盘库
static String STOR_CODE = "FStockPallet";
public void inStorage(JSONObject form){
@@ -36,6 +46,17 @@ public class PalletIostorinvService {
if (count>0){
throw new BadRequestException("入库失败:当前载具信息已经存在");
}
RedissonUtils.lock(()->{
QueryWrapper<StIvtStructattr> query = new QueryWrapper<StIvtStructattr>()
.eq("is_used", true)
.eq("lock_type", StatusEnum.LOCK.code("无锁"))
.eq("stor_code", STOR_CODE)
.isNull("vehicle_code");;
int structCount = iStIvtStructattrService.count(query);
if (structCount< DictConstantPool.STRUCT_COUNT){
throw new BadRequestException("入库失败:当前仓库可用库位小于"+DictConstantPool.STRUCT_COUNT);
}
}, StatusEnum.STRATEGY_TYPE.code("入库")+STOR_CODE,5);
MdPbVehicleMater vehicleMater = new MdPbVehicleMater();
vehicleMater.setId(IdUtil.getStringId());
vehicleMater.setCreate_time(DateUtil.now());
@@ -66,7 +87,19 @@ public class PalletIostorinvService {
flowData.put("stor_code",STOR_CODE);
JSONObject auxParam = new JSONObject();
auxParam.put("target_point",form.getString("target_point"));
RedissonUtils.lock(()->{
List<StructattrVechielDto> vechielDtos = iStIvtStructattrService.collectVechicle(
MapOf.of("material_id", form.getString("material_id")
, "pcsn", form.getString("pcsn")
, "stor_code", STOR_CODE
, "plan_qty", form.getInteger("qty")
, "is_lock", "false"
, "order_by", "ABS(qty-#{plan_qty}) asc,update_time asc")
);
if (vechielDtos.size()<form.getInteger("qty")){
throw new BadRequestException("出库失败:当前仓库可用托盘数量不足");
}
}, StatusEnum.STRATEGY_TYPE.code("出库")+STOR_CODE,5);
BussEventMulticaster.Publish(
new FlowStartEvent("pallet_out",
(proc_inst_id,vehicle) -> {

View File

@@ -82,6 +82,9 @@
#{value}
</foreach>
</if>
<if test="is_lock != null and is_lock != ''">
md_pb_vehicleMater.is_lock == false
</if>
<if test="order_by != null and order_by != ''">
order by ${order_by}
</if>

View File

@@ -31,20 +31,10 @@
<el-form-item label="载具号">
<el-input
v-model="query.vehicle_code_begin"
v-model="query.vehicle_code"
clearable
size="mini"
placeholder="起始载具号"
style="width: 110px;"
class="filter-item"
@keyup.enter.native="crud.toQuery"
/>
-
<el-input
v-model="query.vehicle_code_end"
clearable
size="mini"
placeholder="结束载具号"
placeholder="载具号"
style="width: 110px;"
class="filter-item"
@keyup.enter.native="crud.toQuery"
@@ -90,12 +80,18 @@
<el-form-item label="物料规格" prop="material_spec">
<el-input v-model="materialForm.material_spec" disabled style="width: 370px;"/>
</el-form-item>
<el-form-item label="物料数量" prop="storage_qty">
<el-input v-model="materialForm.storage_qty" clearable style="width: 370px;"/>
</el-form-item>
<el-form-item label="批 次" prop="pcsn">
<el-input v-model="materialForm.pcsn" clearable style="width: 370px;"/>
</el-form-item>
<el-form-item label="物料数量" prop="qty">
<el-input v-model="materialForm.qty" clearable style="width: 370px;"/>
</el-form-item>
<el-form-item label="冻结数量" prop="frozen_qty">
<el-input v-model="materialForm.frozen_qty" clearable style="width: 370px;"/>
</el-form-item>
<el-form-item label="流程实例" prop="proc_inst_id">
<el-input v-model="materialForm.proc_inst_id" clearable style="width: 370px;"/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="text" @click="materiValueCancel()">取消</el-button>