| | |
| | | import com.zy.asrs.service.*; |
| | | import com.zy.common.model.DetlDto; |
| | | import com.zy.common.web.BaseController; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | |
| | | import java.util.*; |
| | | |
| | | @Slf4j |
| | | @RestController |
| | | @RequestMapping("order/pakin") |
| | | public class OrderPakinController extends BaseController { |
| | |
| | | } |
| | | |
| | | // 越库功能:如果勾选了越库订单,无论什么类型的订单都按照越库逻辑处理 |
| | | if (Boolean.TRUE.equals(param.getIsCrossDock())) { |
| | | Boolean isCrossDock = param.getIsCrossDock(); |
| | | log.info("检查越库订单标识,isCrossDock:{},类型:{},订单号:{}", |
| | | isCrossDock, isCrossDock != null ? isCrossDock.getClass().getName() : "null", order.getOrderNo()); |
| | | |
| | | // 判断是否为越库订单(支持 Boolean.TRUE 或 true 字符串) |
| | | boolean shouldProcessCrossDock = Boolean.TRUE.equals(isCrossDock) || |
| | | (isCrossDock != null && isCrossDock.toString().equalsIgnoreCase("true")); |
| | | |
| | | if (shouldProcessCrossDock) { |
| | | log.info("开始处理越库订单,订单号:{},订单ID:{}", order.getOrderNo(), order.getId()); |
| | | String outOrderNo = crossDockService.processCrossDockInbound(order, param, getUserId()); |
| | | // 重新查询订单,确保状态已更新 |
| | | OrderPakin finalOrder = orderService.selectById(order.getId()); |
| | | if (finalOrder != null) { |
| | | log.info("越库订单处理完成,订单号:{},最终状态:{}", finalOrder.getOrderNo(), finalOrder.getSettle()); |
| | | } |
| | | return R.ok("越库入库单创建成功,已自动生成越库出库单:" + outOrderNo); |
| | | } else { |
| | | log.info("非越库订单,订单号:{},状态保持为:{}", order.getOrderNo(), order.getSettle()); |
| | | } |
| | | |
| | | return R.ok("订单添加成功"); |
| | |
| | | import com.baomidou.mybatisplus.annotations.TableField; |
| | | import com.core.common.Cools; |
| | | import com.core.common.SpringUtils; |
| | | import com.zy.common.properties.CrossDockProperties; |
| | | import com.zy.system.entity.User; |
| | | import com.zy.system.service.UserService; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | |
| | | return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.appe_time); |
| | | } |
| | | |
| | | /** |
| | | * 格式化库位号显示,如果是虚拟库位则显示"越库"标识 |
| | | * |
| | | * @return 格式化后的库位号(如果是虚拟库位,格式为:库位号(越库)) |
| | | */ |
| | | public String getLocNo$() { |
| | | if (Cools.isEmpty(this.loc_no)) { |
| | | return ""; |
| | | } |
| | | try { |
| | | CrossDockProperties crossDockProperties = SpringUtils.getBean(CrossDockProperties.class); |
| | | if (crossDockProperties != null && this.loc_no.equals(crossDockProperties.getVirtualLocationNo())) { |
| | | return this.loc_no + "(越库)"; |
| | | } |
| | | } catch (Exception e) { |
| | | // 如果获取配置失败,忽略异常,返回原始库位号 |
| | | } |
| | | return this.loc_no; |
| | | } |
| | | |
| | | } |
| | |
| | | */ |
| | | private Boolean isCrossDock; |
| | | |
| | | /** |
| | | * 出库订单类型(越库订单时使用) |
| | | * 用户选择的出库订单类型ID |
| | | */ |
| | | private Long outboundDocType; |
| | | |
| | | private List<OrderDetl> orderDetlList; |
| | | private List<OrderDetlPakin> orderDetlPakinList; |
| | | private List<OrderDetlPakout> orderDetlPakoutList; |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public String processCrossDockInbound(OrderPakin order, OrderDomainParam param, Long userId) { |
| | | log.info("开始处理越库入库单,订单号:{}", order.getOrderNo()); |
| | | log.info("开始处理越库入库单,订单号:{},订单类型:{}", order.getOrderNo(), order.getDocType()); |
| | | |
| | | Date now = new Date(); |
| | | |
| | | // 步骤1:设置入库单为已上报状态(跳过ERP上报流程) |
| | | log.info("步骤1:设置入库单[{}]为已上报状态", order.getOrderNo()); |
| | | if (!orderPakinService.updateSettle(order.getId(), 6L, userId)) { |
| | | throw new CoolException("设置入库单为已上报状态失败"); |
| | | log.info("步骤1:设置入库单[{}]为已上报状态,订单ID:{}", order.getOrderNo(), order.getId()); |
| | | boolean updateResult = orderPakinService.updateSettle(order.getId(), 6L, userId); |
| | | log.info("步骤1:更新入库单状态结果:{}", updateResult); |
| | | if (!updateResult) { |
| | | throw new CoolException("设置入库单为已上报状态失败,订单ID:" + order.getId()); |
| | | } |
| | | // 验证状态是否更新成功 |
| | | OrderPakin updatedOrder = orderPakinService.selectById(order.getId()); |
| | | if (updatedOrder != null) { |
| | | log.info("步骤1:验证入库单状态更新,订单号:{},当前状态:{}", updatedOrder.getOrderNo(), updatedOrder.getSettle()); |
| | | if (!updatedOrder.getSettle().equals(6L)) { |
| | | throw new CoolException("入库单状态更新失败,期望状态:6,实际状态:" + updatedOrder.getSettle()); |
| | | } |
| | | } |
| | | |
| | | // 步骤2:更新明细完成数量并创建虚拟库位库存 |
| | |
| | | new EntityWrapper<OrderDetlPakin>().eq("order_id", order.getId())); |
| | | |
| | | for (OrderDetlPakin orderDetl : orderDetls) { |
| | | // 2.1 更新完成数量 |
| | | orderDetl.setQty(orderDetl.getAnfme()); |
| | | // 2.1 更新完成数量和作业数量(越库订单立即完成,不需要实际作业) |
| | | orderDetl.setQty(orderDetl.getAnfme()); // 完成数量等于申请数量 |
| | | orderDetl.setWorkQty(orderDetl.getAnfme()); // 作业数量等于申请数量 |
| | | orderDetl.setUpdateBy(userId); |
| | | orderDetl.setUpdateTime(now); |
| | | if (!orderDetlPakinService.updateById(orderDetl)) { |
| | |
| | | } |
| | | |
| | | // 步骤3:获取越库出库单类型 |
| | | Long outboundDocTypeId = crossDockProperties.getOutboundDocTypeId(); |
| | | log.info("步骤3:获取越库出库单类型,docId={}", outboundDocTypeId); |
| | | // 优先使用用户选择的出库订单类型,如果没有则使用配置的默认类型 |
| | | Long outboundDocTypeId = param.getOutboundDocType(); |
| | | if (outboundDocTypeId == null) { |
| | | outboundDocTypeId = crossDockProperties.getOutboundDocTypeId(); |
| | | log.info("步骤3:用户未选择出库订单类型,使用配置的默认类型,docId={}", outboundDocTypeId); |
| | | } else { |
| | | log.info("步骤3:使用用户选择的出库订单类型,docId={}", outboundDocTypeId); |
| | | } |
| | | DocType crossDockOutDocType = docTypeService.selectById(outboundDocTypeId); |
| | | if (crossDockOutDocType == null) { |
| | | throw new CoolException("越库出库单类型不存在,docId=" + outboundDocTypeId); |
| | | } |
| | | log.info("步骤3:出库订单类型名称:{}", crossDockOutDocType.getDocName()); |
| | | |
| | | // 步骤4:创建越库出库单主档 |
| | | log.info("步骤4:创建越库出库单主档"); |
| | |
| | | outDetl.setId(null); // 清除ID,让数据库自动生成 |
| | | outDetl.setOrderId(outOrder.getId()); |
| | | outDetl.setOrderNo(outOrderNo); |
| | | outDetl.setAnfme(inDetl.getAnfme()); // 申请数量等于入库单明细的申请数量 |
| | | outDetl.setQty(inDetl.getAnfme()); // 完成数量等于申请数量 |
| | | outDetl.setWorkQty(inDetl.getAnfme()); |
| | | outDetl.setWorkQty(inDetl.getAnfme()); // 作业数量等于申请数量 |
| | | outDetl.setCreateBy(userId); |
| | | outDetl.setCreateTime(now); |
| | | outDetl.setUpdateBy(userId); |
| | |
| | | form.val('editForm', expTpe); |
| | | if (expTpe) { |
| | | $('#orderNo').attr("disabled", "disabled"); |
| | | // 修改订单时,不显示越库按钮(因为越库订单创建后就完成了,不会有中间状态) |
| | | $('#crossDockItem').hide(); |
| | | } else { |
| | | // 新增订单时,显示越库按钮,默认不勾选 |
| | | $('#crossDockItem').show(); |
| | | // 默认隐藏出库订单类型选择器 |
| | | $('#outboundDocTypeItem').hide(); |
| | | } |
| | | |
| | | // 先渲染 switch,确保 LayUI 正确初始化 |
| | | form.render('switch'); |
| | | |
| | | // 初始化出库订单类型选择器 |
| | | var outboundDocTypeData = []; |
| | | $.ajax({ |
| | | url: baseUrl + "/docType/list/auth", |
| | | headers: { 'token': localStorage.getItem('token') }, |
| | | data: { limit: 9999, pakout: 1 }, |
| | | method: 'POST', |
| | | async: false, |
| | | success: function (res) { |
| | | if (res.code === 200) { |
| | | // 转换为 xmSelect 需要的格式 |
| | | res.data.records.forEach(function (item) { |
| | | outboundDocTypeData.push({ |
| | | name: item.docName, |
| | | value: item.docId |
| | | }); |
| | | }); |
| | | } else { |
| | | layer.msg(res.msg, { icon: 2 }); |
| | | } |
| | | } |
| | | }); |
| | | var outboundDocTypeXmSelect = xmSelect.render({ |
| | | el: '#outboundDocTypeSelect', |
| | | radio: true, |
| | | clickClose: true, |
| | | filterable: true, |
| | | model: { |
| | | icon: 'hidden', |
| | | label: { |
| | | type: 'text', |
| | | } |
| | | }, |
| | | data: outboundDocTypeData, |
| | | initValue: [] |
| | | }); |
| | | |
| | | // 切换出库订单类型选择器的显示/隐藏 |
| | | function toggleOutboundDocTypeSelector(show) { |
| | | if (show) { |
| | | // 勾选越库订单时,显示出库订单类型选择器 |
| | | $('#outboundDocTypeItem').show(); |
| | | console.log('显示出库订单类型选择器'); |
| | | } else { |
| | | // 取消勾选时,隐藏出库订单类型选择器 |
| | | $('#outboundDocTypeItem').hide(); |
| | | outboundDocTypeXmSelect.setValue([]); |
| | | console.log('隐藏出库订单类型选择器'); |
| | | } |
| | | } |
| | | |
| | | // 监听 switch 变化,控制出库订单类型选择器的显示/隐藏 |
| | | // 注意:必须在 form.render 之后注册监听器 |
| | | form.on('switch(isCrossDock)', function(data){ |
| | | var isChecked = data.elem.checked; |
| | | console.log('越库订单开关变化,值:', isChecked, '元素:', data.elem); |
| | | toggleOutboundDocTypeSelector(isChecked); |
| | | }); |
| | | |
| | | // 初始化时检查 switch 状态(以防页面刷新后状态不一致) |
| | | // 使用 setTimeout 确保 DOM 已完全渲染 |
| | | setTimeout(function() { |
| | | var initialCrossDockState = $('#isCrossDock').is(':checked') || |
| | | $('#isCrossDock').prop('checked') || |
| | | ($('#isCrossDock').next('.layui-form-switch').hasClass('layui-form-onswitch')); |
| | | console.log('初始化检查越库订单状态:', initialCrossDockState); |
| | | if (initialCrossDockState) { |
| | | toggleOutboundDocTypeSelector(true); |
| | | } |
| | | }, 100); |
| | | // 初始化业务时间日期选择器 |
| | | layDate.render({ |
| | | elem: '#orderTime', |
| | |
| | | return false; |
| | | } |
| | | } |
| | | // 获取越库订单开关状态(多种方式检测,确保准确性) |
| | | var isCrossDockChecked = $('#isCrossDock').is(':checked') || |
| | | $('#isCrossDock').prop('checked') || |
| | | data.field.isCrossDock === 'ON' || |
| | | data.field.isCrossDock === true || |
| | | data.field.isCrossDock === 'on'; |
| | | console.log('提交越库订单状态,isCrossDock:', isCrossDockChecked, '原始值:', data.field.isCrossDock, 'DOM checked:', $('#isCrossDock').is(':checked')); |
| | | |
| | | // 获取出库订单类型ID |
| | | var outboundDocTypeId = null; |
| | | if (isCrossDockChecked) { |
| | | // 检查出库订单类型选择器是否可见 |
| | | if (!$('#outboundDocTypeItem').is(':visible')) { |
| | | console.warn('出库订单类型选择器未显示,但越库订单已勾选'); |
| | | } |
| | | var outboundDocTypeValue = outboundDocTypeXmSelect.getValue(); |
| | | console.log('出库订单类型选择器值:', outboundDocTypeValue); |
| | | if (!outboundDocTypeValue || outboundDocTypeValue.length === 0 || !outboundDocTypeValue[0]) { |
| | | layer.msg('请选择出库订单类型', { icon: 2 }); |
| | | return false; |
| | | } |
| | | outboundDocTypeId = Number(outboundDocTypeValue[0].value); |
| | | console.log('出库订单类型ID:', outboundDocTypeId); |
| | | } |
| | | |
| | | layer.load(2); |
| | | |
| | | $.ajax({ |
| | | url: baseUrl + "/order/pakin/order/form/" + (isExpAdd ? "add" : "modify") + "/auth", |
| | | headers: { 'token': localStorage.getItem('token') }, |
| | |
| | | orderNo: data.field.orderNo, |
| | | cstmrName: cstmrXmSelect.getValue()[0] ? cstmrXmSelect.getValue()[0].name : null, |
| | | orderTime: data.field.orderTime, |
| | | isCrossDock: isCrossDockChecked, |
| | | outboundDocType: outboundDocTypeId, |
| | | orderDetlPakinList: nList |
| | | }), |
| | | contentType: 'application/json;charset=UTF-8', |
| | |
| | | var cols = [ |
| | | {field: 'appeTime$', title: '入库时间', align: 'center', width: 200} |
| | | ,{field: 'stay_time', align: 'center',title: '滞留天数'} |
| | | ,{field: 'loc_no', align: 'center',title: '库位号'} |
| | | ,{field: 'locNo$', title: '库位号', align: 'center'} |
| | | ]; |
| | | cols.push.apply(cols, detlCols); |
| | | return cols; |
| | |
| | | var cols = [ |
| | | {field: 'appeTime$', title: '入库时间', align: 'center', width: 200} |
| | | ,{field: 'stay_time', align: 'center',title: '滞留天数'} |
| | | ,{field: 'loc_no', align: 'center',title: '库位号'} |
| | | ,{field: 'locNo$', title: '库位号', align: 'center'} |
| | | ]; |
| | | cols.push.apply(cols, detlCols); |
| | | return cols; |
| | |
| | | <input id="orderTime" name="orderTime" placeholder="选择业务时间" type="text" class="layui-input" autocomplete="off" lay-verType="tips" /> |
| | | </div> |
| | | </div> |
| | | <div class="layui-form-item" id="crossDockItem" style="display: none;"> |
| | | <label class="layui-form-label">越库订单:</label> |
| | | <div class="layui-input-block"> |
| | | <input type="checkbox" id="isCrossDock" name="isCrossDock" lay-skin="switch" lay-text="是|否" lay-filter="isCrossDock" title="勾选后,无论什么类型的订单都按照越库逻辑处理,过账入库+出库直接完成,不调用任何设备和通知其他系统"> |
| | | </div> |
| | | </div> |
| | | <div class="layui-form-item" id="outboundDocTypeItem" style="display: none;"> |
| | | <label class="layui-form-label">出库订单类型:</label> |
| | | <div class="layui-input-block"> |
| | | <div id="outboundDocTypeSelect"></div> |
| | | <div class="layui-form-mid layui-word-aux">选择越库订单生成的出库单类型</div> |
| | | </div> |
| | | </div> |
| | | <div class="layui-form-item" style="position: relative;"> |
| | | <label class="layui-form-label">单据明细:</label> |
| | | <div class="layui-input-block"> |