| src/main/java/com/zy/asrs/controller/WorkController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/zy/asrs/entity/param/StockOutParam.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/zy/asrs/service/WorkService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/zy/asrs/service/impl/MobileServiceImpl.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/zy/asrs/task/handler/WorkLogHandler.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/webapp/static/js/pakStore/stockOutToP.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/webapp/views/pakStore/stockOutToP.html | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/main/java/com/zy/asrs/controller/WorkController.java
@@ -119,6 +119,13 @@ return R.ok("出库启动成功"); } @RequestMapping("/plate/outToP/start") @ManagerAuth(memo = "出库作业") public R fullStoreTakeStartToP(@RequestBody StockOutParam param) { workService.startupFullTakeStoreToP(param, getUserId()); return R.ok("出库启动成功"); } @RequestMapping("/empty/plate/in/start") @ManagerAuth(memo = "空板入库") public R emptyPlateInStart(@RequestParam Integer sourceStaNo) { src/main/java/com/zy/asrs/entity/param/StockOutParam.java
@@ -13,6 +13,8 @@ // 出站口 private Integer outSite; private String warehouse; // 物料编号集合 private List<LocDetl> locDetls; @@ -40,6 +42,14 @@ this.fbillNo = fbillNo; } public String getWarehouse() { return warehouse; } public void setWarehouse(String warehouse) { this.warehouse = warehouse; } public static class LocDetl { // 库位号 src/main/java/com/zy/asrs/service/WorkService.java
@@ -19,6 +19,8 @@ */ void startupFullTakeStore(StockOutParam param, Long userId); void startupFullTakeStoreToP(StockOutParam param, Long userId); /** * 出库作业 * @param staNo 目标站点 src/main/java/com/zy/asrs/service/impl/MobileServiceImpl.java
@@ -54,6 +54,8 @@ private LocDetlService locDetlService; @Autowired private LocNormalService locNormalService; @Autowired private LocNormalLogService locNormalLogService; @Override @Transactional @@ -352,6 +354,17 @@ }else { throw new CoolException("库存数据有误"); } // 生成平仓出入库记录 LocNormalLog locLog = new LocNormalLog(); VersionUtils.setLocNormalLog(locLog, locNormal); locLog.setAnfme(waitPakin.getAnfme()); locLog.setIoType(2); locLog.setCreateTime(new Date()); locLog.setCreateUser(9527L); if (!locNormalLogService.insert(locLog)) { String logStr = JSON.toJSONString(locLog); log.info("平仓入库记录插入失败,数据:" + logStr); } } } src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java
@@ -221,6 +221,35 @@ @Override @Transactional public void startupFullTakeStoreToP(StockOutParam param, Long userId) { // 目标站点状态检测 BasDevp staNo = basDevpService.checkSiteStatus(param.getOutSite()); int agvSite = 0; if (!Cools.isEmpty(staNo.getFronting()) && staNo.getFronting().equals("Y")) { agvSite = staNo.getDevNo(); staNo = basDevpService.checkSiteStatus(201); } // 获取库位明细 List<LocDetlDto> locDetlDtos = new ArrayList<>(); for (StockOutParam.LocDetl paramLocDetl : param.getLocDetls()) { if (!Cools.isEmpty(paramLocDetl.getLocNo(), paramLocDetl.getMatnr(), paramLocDetl.getCount())) { LocDetl sqlParam = new LocDetl(); sqlParam.setLocNo(paramLocDetl.getLocNo()); sqlParam.setMatnr(paramLocDetl.getMatnr()); LocDetl one = locDetlService.selectOne(new EntityWrapper<>(sqlParam)); if (null != one) locDetlDtos.add(new LocDetlDto(one, paramLocDetl.getCount())); } } if (!locDetlDtos.isEmpty()) { // 启动出库开始 101.出库 stockOutToP(staNo, locDetlDtos, null, userId, agvSite,param.getWarehouse()); } else { throw new CoolException("库位物料不存在"); } } @Override @Transactional public void stockOut(BasDevp staNo, List<LocDetlDto> locDetlDtos, Integer ioType, Long userId, Integer agvSite) { // 合并同类项 Set<String> locNos = new HashSet<>(); @@ -327,6 +356,116 @@ // 同一列的同时出库,则优先出浅库位 } @Transactional public void stockOutToP(BasDevp staNo, List<LocDetlDto> locDetlDtos, Integer ioType, Long userId, Integer agvSite ,String warehouse) { // 合并同类项 Set<String> locNos = new HashSet<>(); locDetlDtos.forEach(dto -> locNos.add(dto.getLocDetl().getLocNo())); List<OutLocDto> dtos = new ArrayList<>(); for (String locNo : locNos) { List<LocDetlDto> list = new ArrayList<>(); Iterator<LocDetlDto> iterator = locDetlDtos.iterator(); while (iterator.hasNext()) { LocDetlDto dto = iterator.next(); if (locNo.equals(dto.getLocDetl().getLocNo())) { list.add(dto); iterator.remove(); } } dtos.add(new OutLocDto(locNo, list)); } // 生成工作档 for (OutLocDto dto : dtos) { // 判断入出库类型:101.全板出库 or 103.拣料出库 if (ioType == null) { ioType = dto.isAll() ? 101 : 103; } // 获取库位 LocMast locMast = locMastService.selectById(dto.getLocNo()); // 获取路径 Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>() .eq("type_no", ioType) .eq("stn_no", staNo.getDevNo()) .eq("crn_no", locMast.getCrnNo()); StaDesc staDesc = staDescService.selectOne(wrapper); if (Cools.isEmpty(staDesc)) { throw new CoolException("出库路径不存在"); } // 生成工作号 int workNo = commonService.getWorkNo(DEFAULT_WORK_NO_TYPE); // 生成工作档 WrkMast wrkMast = new WrkMast(); wrkMast.setWrkNo(workNo); wrkMast.setIoTime(new Date()); wrkMast.setWrkSts(11L); // 工作状态:11.生成出库ID wrkMast.setIoType(ioType); // 入出库状态 wrkMast.setIoPri(13D); // 优先级:13 wrkMast.setCrnNo(locMast.getCrnNo()); wrkMast.setSourceStaNo(staDesc.getCrnStn()); // 源站 wrkMast.setStaNo(staDesc.getStnNo()); // 目标站 wrkMast.setSourceLocNo(dto.getLocNo()); // 源库位 wrkMast.setBarcode(locMast.getBarcode()); // 条码 wrkMast.setFullPlt("Y"); // 满板:Y wrkMast.setPicking("N"); // 拣料 wrkMast.setExitMk("N"); // 退出 wrkMast.setEmptyMk("N"); // 空板 wrkMast.setLinkMis("N"); wrkMast.setCtnKind(agvSite); // 出库下的小车工作区站好 wrkMast.setExitMk("N"); // 小车是否搬运 wrkMast.setAppeUser(userId); // 操作人员数据 wrkMast.setAppeTime(new Date()); wrkMast.setModiUser(userId); wrkMast.setModiTime(new Date()); wrkMast.setPdcType("Y"); //用作移库标记 wrkMast.setLogErrMemo(warehouse); //用作存储仓库标记 if (!wrkMastService.insert(wrkMast)) { throw new CoolException("保存工作档失败,出库库位号:" + dto.getLocNo()); } // 生成工作档明细 for (LocDetlDto detlDto : dto.getLocDetlDtos()) { // 如果为捡料出库需要判断托盘码是否为空 if (ioType == 103) { String zpallet = detlDto.getLocDetl().getZpallet(); if (Cools.isEmpty(zpallet)) { throw new CoolException("拣料出库必须含有托盘码"); } } // 出库时,数量为0的直接忽略 if (detlDto.getCount() == null || detlDto.getCount() <= 0.0D) { continue; } WrkDetl wrkDetl = new WrkDetl(); wrkDetl.setWrkNo(workNo); wrkDetl.setIoTime(new Date()); Double anfme = ioType == 101 ? detlDto.getLocDetl().getAnfme() : detlDto.getCount(); wrkDetl.setAnfme(anfme); // 数量 VersionUtils.setWrkDetl(wrkDetl, detlDto.getLocDetl()); // 版本控制 wrkDetl.setAppeTime(new Date()); wrkDetl.setAppeUser(userId); wrkDetl.setModiTime(new Date()); wrkDetl.setModiUser(userId); if (!wrkDetlService.insert(wrkDetl)) { throw new CoolException("保存工作档明细失败"); } } // 修改库位状态: F.在库 ====>>> R.出库预约/P.拣料/盘点/并板出库中 locMast = locMastService.selectById(dto.getLocNo()); if (locMast.getLocSts().equals("F")) { locMast.setLocSts(ioType == 101 ? "R" : "P"); locMast.setModiUser(userId); locMast.setModiTime(new Date()); if (!locMastService.updateById(locMast)) { throw new CoolException("预约库位状态失败,库位号:" + dto.getLocNo()); } } else { throw new CoolException(dto.getLocNo() + "库位不是在库状态"); } } // todo:luxiaotao // 同一列的同时出库,则优先出浅库位 } @Override @Transactional public String emptyPlateIn(Integer devpNo, Long userId) { src/main/java/com/zy/asrs/task/handler/WorkLogHandler.java
@@ -1,14 +1,14 @@ package com.zy.asrs.task.handler; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.mapper.Wrapper; import com.core.common.Cools; import com.zy.asrs.entity.WaitPakin; import com.zy.asrs.entity.WrkDetl; import com.zy.asrs.entity.WrkMast; import com.zy.asrs.entity.*; import com.zy.asrs.service.*; import com.zy.asrs.task.AbstractHandler; import com.zy.asrs.task.core.ReturnT; import com.zy.asrs.utils.VersionUtils; import com.zy.common.service.erp.ErpService; import com.zy.common.service.erp.entity.OutStockBillEntry; import lombok.extern.slf4j.Slf4j; @@ -20,6 +20,8 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.math.BigDecimal; import java.util.Date; import java.util.List; /** @@ -50,6 +52,10 @@ private JdbcTemplate jdbcTemplate; @Autowired private OutStockDanService outStockDanService; @Autowired private LocNormalService locNormalService; @Autowired private LocNormalLogService locNormalLogService; @Transactional public ReturnT<Exception> start(WrkMast wrkMast) { @@ -99,6 +105,59 @@ } } } if (wrkMast.getPdcType().equals("Y")){ List<WrkDetl> wrkDetls = wrkDetlService.selectList(new EntityWrapper<WrkDetl>().eq("wrk_no", wrkMast.getWrkNo())); if (Cools.isEmpty(wrkDetls)){ log.error("出库(移库)作业时,未查询到工作明细"); }else { for (WrkDetl wrkDetl : wrkDetls) { EntityWrapper<LocNormal> locNormalEntityWrapper = new EntityWrapper<>(); locNormalEntityWrapper.eq("matnr",wrkDetl.getMatnr()); locNormalEntityWrapper.eq("mnemonic",wrkDetl.getMnemonic()); locNormalEntityWrapper.eq("state","1"); locNormalEntityWrapper.eq("warehouse",wrkMast.getLogErrMemo()); LocNormal locNormal = locNormalService.selectOne(locNormalEntityWrapper); if (Cools.isEmpty(locNormal)){ Date now = new Date(); LocNormal locNormal1 = new LocNormal(); locNormal1.setMatnr(wrkDetl.getMatnr()); locNormal1.setMaktx(wrkDetl.getMaktx()); locNormal1.setLgnum(wrkDetl.getLgnum()); locNormal1.setType(wrkDetl.getType()); locNormal1.setMnemonic(wrkDetl.getMnemonic()); locNormal1.setSupplier(wrkDetl.getSupplier()); locNormal1.setWarehouse(wrkMast.getLogErrMemo()); locNormal1.setAnfme(BigDecimal.valueOf(wrkDetl.getAnfme())); locNormal1.setModiTime(now); locNormal1.setModiUser(9527L); locNormal1.setAppeUser(9527L); locNormal1.setAppeTime(now); locNormal1.setState("1"); boolean insert = locNormalService.insert(locNormal1); if (!insert){ log.error("出库(移库)作业时,插入平库物料失败"); } // 生成平仓出入库记录 LocNormalLog locLog = new LocNormalLog(); VersionUtils.setLocNormalLog(locLog, locNormal1); locLog.setAnfme(locNormal1.getAnfme().doubleValue()); locLog.setIoType(1); locLog.setCreateTime(new Date()); locLog.setCreateUser(9527L); if (!locNormalLogService.insert(locLog)) { String logStr = JSON.toJSONString(locLog); log.info("平仓入库记录插入失败,数据:" + logStr); } }else { locNormal.setAnfme(locNormal.getAnfme().add(BigDecimal.valueOf(wrkDetl.getAnfme()))); boolean update = locNormalService.update(locNormal, locNormalEntityWrapper); if (!update){ log.error("出库(移库)作业时,更新平库物料失败"); } } } } } // 保存工作主档历史档 if (!wrkMastLogService.save(wrkMast.getWrkNo())) { src/main/webapp/static/js/pakStore/stockOutToP.js
New file @@ -0,0 +1,212 @@ var locDetlData = []; function getCol() { var cols = [ // {field: 'count', align: 'center',title: '出库数量', edit:'text', width: 130, style:'color: blue;font-weight: bold'} {field: 'anfme', align: 'center',title: '数量', edit: 'text', style: 'color: blue;font-weight: bold'} ,{field: 'locNo$', align: 'center',title: '库位号'} ]; arrRemove(detlCols, 'field', 'anfme'); cols.push.apply(cols, detlCols); // cols.push({fixed: 'right', title:'操作', align: 'center', toolbar: '#operate', width:80}) return cols; } layui.use(['table','laydate', 'form'], function() { var table = layui.table; var $ = layui.jquery; var layer = layui.layer; var form = layui.form; tableIns = table.render({ elem: '#chooseData', headers: {token: localStorage.getItem('token')}, data: [], even: true, toolbar: '#toolbar', cellMinWidth: 50, cols: [getCol()], done: function(res, curr, count) { limit(); getOutBound(); getOutBound2() } }); // 页面修改 table.on('edit(chooseData)', function (obj) { updateLocDetlData(obj.data.locNo, obj.data.matnr, Number(obj.value)); }); // 监听头工具栏事件 table.on('toolbar(chooseData)', function (obj) { var data = locDetlData; switch (obj.event) { case 'outbound': if (data.length === 0){ layer.msg('请先添加库位物料'); } else { var staNo = $("#staNoSelect").val(); var warehouse = $("#warehouseSelect").val() if (staNo === "" || staNo === null){ layer.msg("请选择出库口"); return; } if (warehouse === "" || warehouse === null){ layer.msg("请选择库区"); return; } var locDetls = []; data.forEach(function(elem) { locDetls.push({locNo: elem.locNo, matnr: elem.matnr, count: elem.count}); }); let param = { outSite: staNo, warehouse:warehouse, locDetls: locDetls } $.ajax({ url: baseUrl+"/plate/outToP/start", headers: {'token': localStorage.getItem('token')}, data: JSON.stringify(param), contentType:'application/json;charset=UTF-8', method: 'POST', success: function (res) { if (res.code === 200){ locDetlData = []; tableIns.reload({data: locDetlData,done:function (res) {limit();getOutBound();}}); layer.msg(res.msg); } else if (res.code === 403){ top.location.href = baseUrl+"/"; } else { layer.msg(res.msg) } } }); } break; } }); // 监听行工具事件 table.on('tool(chooseData)', function(obj){ var data = obj.data; switch (obj.event) { case 'remove': for (var i = locDetlData.length - 1; i >= 0; i--) { if (locDetlData[i].locNo === data.locNo && locDetlData[i].matnr === data.matnr) { locDetlData.splice(i, 1); } } tableIns.reload({data: locDetlData,done:function (res) {limit();getOutBound();}}); break; } }); function updateLocDetlData(locNo, matnr, count) { if (isNaN(count)) { layer.msg("请输入数字"); } else { if (count > 0) { for (var i=0;i<locDetlData.length;i++){ if (locDetlData[i]["locNo"] === locNo && locDetlData[i]["matnr"] === matnr){ if (count > locDetlData[i]["anfme"]) { layer.msg("不能超过原数量"); } else { locDetlData[i]["anfme"] = count; locDetlData[i]["count"] = count; } break; } } } else { layer.msg("数量必须大于零"); } } tableIns.reload({data: locDetlData,done:function (res) {limit(); getOutBound();}}); } // 获取出库口 function getOutBound(){ $.ajax({ url: baseUrl+"/available/take/site", headers: {'token': localStorage.getItem('token')}, method: 'POST', async: false, success: function (res) { if (res.code === 200){ var tpl = $("#takeSiteSelectTemplate").html(); var template = Handlebars.compile(tpl); var html = template(res); $('#staNoSelect').append(html); form.render('select'); } else if (res.code === 403){ top.location.href = baseUrl+"/"; }else { layer.msg(res.msg) } } }) } function getOutBound2(){ $.ajax({ url: baseUrl + "/locArea/queryAll/auth?areaType=", headers: {'token': localStorage.getItem('token')}, method: 'POST', success: function (res) { if (res.code === 200) { var html = ""; if (res.data && res.data.length > 0) { html += res.data.map(function (item) { return "<Option value=" + item.uuid + ">" + item.name + "</Option>"; }); } $('#warehouseSelect').append(html); layui.form.render('select'); } else if (res.code === 403) { top.location.href = baseUrl + "/pda"; } else { layer.msg(res.msg) } } }); } }) // 提取物料 var locDetlLayerIdx; function getLocDetl() { locDetlLayerIdx = layer.open({ type: 2, title: '提取出货内容', maxmin: true, area: [top.detailWidth, top.detailHeight], shadeClose: true, content: 'locDetlQuery.html', success: function(layero, index){ } }); } // 添加表格数据 function addTableData(data) { for (var i=0;i<data.length;i++){ let pass = false; for (var j=0;j<locDetlData.length;j++){ if (data[i].matnr === locDetlData[j].matnr && data[i].locNo$ === locDetlData[j].locNo$) { pass = true; break; } } if (pass) { data.splice(i--, 1); } else { data[i]["count"] = data[i]["anfme"]; } } locDetlData.push.apply(locDetlData, data); tableIns.reload({data: locDetlData}); layer.close(locDetlLayerIdx); } src/main/webapp/views/pakStore/stockOutToP.html
New file @@ -0,0 +1,140 @@ <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title></title> <meta name="renderer" content="webkit"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all"> <link rel="stylesheet" href="../../static/css/cool.css" media="all"> <link rel="stylesheet" href="../../static/css/common.css" media="all"> <style> html { height: 100%; padding: 10px; background-color: #f1f1f1; } body { background-color: #fff; border-radius: 5px; box-shadow: 0 0 3px rgba(0,0,0,.3); padding-bottom: 20px; } #staNoSpan { text-align: center; display: inline-block; width: 100px; font-size: 13px; } #warehouseSpan { text-align: center; display: inline-block; width: 100px; font-size: 13px; } .layui-btn-container .layui-form-select { display: inline-block; width: 150px; height: 30px; } .layui-btn-container .layui-form-select.layui-form-selected { display: inline-block; width: 150px; } .layui-btn-container .layui-select-title input { font-size: 13px; } .layui-btn-container .layui-anim.layui-anim-upbit dd { font-size: 13px; } #btn-outbound { margin-left: 60px; display: none; } /*----------------------------------*/ .function-area { padding: 20px 50px; } .function-btn { font-size: 16px; padding: 1px 1px 1px 1px; width: 100px; height: 50px; border-color: #2b425b; border-radius: 4px; border-width: 2px; background: none; border-style: solid; transition: 0.4s; cursor: pointer; letter-spacing: 3px; } .function-btn:hover { background-color: #2b425b; color: #fff; } #mat-query { display: none; } </style> </head> <body> <!-- 功能区 --> <div class="function-area"> <button id="mat-query" class="function-btn" onclick="getLocDetl()">新增</button> </div> <hr> <!-- 表格 --> <div style="padding-bottom: 5px; margin-bottom: 45px"> <!-- 头部 --> <script type="text/html" id="toolbar"> <div class="layui-form"> <div class="layui-btn-container"> <!-- 1.选择出库口 --> <span id="staNoSpan">出库口:</span> <select id="staNoSelect" lay-verify="required"> <option value="">请选择站点</option> </select> <span id="warehouseSpan">移库库区:</span> <select id="warehouseSelect" lay-verify="required"> <option value="">请选择库区</option> </select> <!-- 2.启动出库 --> <button class="layui-btn layui-btn-lg" id="btn-outbound" lay-event="outbound">启动出库</button> </div> </div> </script> <!-- 行 --> <script type="text/html" id="operate"> <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="remove">移除</a> </script> <table class="layui-table" id="chooseData" lay-filter="chooseData"></table> </div> <script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script> <script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script> <script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script> <script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script> <script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script> <script type="text/javascript" src="../../static/js/pakStore/stockOutToP.js" charset="utf-8"></script> <script type="text/template" id="takeSiteSelectTemplate"> {{#each data}} <option value="{{siteId}}">{{desc}}</option> {{/each}} </script> </body> </html>