Browse Source

退库

master
常熟吴彦祖 4 days ago
parent
commit
86289c0be5
  1. 23
      src/main/java/com/heai/modules/app/controller/PageController.java
  2. 53
      src/main/java/com/heai/modules/app/controller/TransferNoticeReturnPdaController.java
  3. 36
      src/main/java/com/heai/modules/app/dao/TransferNoticeReturnDao.java
  4. 18
      src/main/java/com/heai/modules/app/entity/TransferNoticeReturnConfirmData.java
  5. 32
      src/main/java/com/heai/modules/app/entity/TransferNoticeReturnLineData.java
  6. 36
      src/main/java/com/heai/modules/app/entity/TransferNoticeReturnNoticeRow.java
  7. 32
      src/main/java/com/heai/modules/app/entity/TransferNoticeReturnScanResult.java
  8. 14
      src/main/java/com/heai/modules/app/entity/TransferNoticeReturnValidateData.java
  9. 38
      src/main/java/com/heai/modules/app/service/TransferNoticeReturnPdaService.java
  10. 563
      src/main/java/com/heai/modules/app/service/impl/TransferNoticeReturnPdaServiceImpl.java
  11. 55
      src/main/resources/mapper/app/TransferNoticeReturn.xml
  12. 137
      src/main/resources/static/js/pdaOther/transferNoticeReturnStep1.js
  13. 279
      src/main/resources/static/js/pdaOther/transferNoticeReturnStep2.js
  14. 152
      src/main/resources/templates/pdaOther/transferNoticeReturnStep1.ftl
  15. 120
      src/main/resources/templates/pdaOther/transferNoticeReturnStep2.ftl

23
src/main/java/com/heai/modules/app/controller/PageController.java

@ -599,7 +599,8 @@ public class PageController {
/**
* PDA 袋装标签生产退库 步骤1 - rqrq
*/
@GetMapping("/pdaOther/productionBagReturnStep1")
// @GetMapping("/pdaOther/productionBagReturnStep1")
@GetMapping("/pdaOther/productionBagReturnStep1_old")
public String productionBagReturnStep1(String menuId, String titleName, Model model) {
model.addAttribute("menuId", menuId);
model.addAttribute("titleName", titleName);
@ -616,6 +617,26 @@ public class PageController {
return "/pdaOther/productionBagReturnStep2";
}
/**
* PDA 扫入库通知单退库 步骤1 - rqrq
*/
@GetMapping("/pdaOther/productionBagReturnStep1")
public String transferNoticeReturnStep1(String menuId, String titleName, Model model) {
model.addAttribute("menuId", menuId);
model.addAttribute("titleName", titleName);
return "/pdaOther/transferNoticeReturnStep1";
}
/**
* PDA 扫入库通知单退库 步骤2 - rqrq
*/
@GetMapping("/pdaOther/transferNoticeReturnStep2")
public String transferNoticeReturnStep2(String menuId, String titleName, Model model) {
model.addAttribute("menuId", menuId);
model.addAttribute("titleName", titleName);
return "/pdaOther/transferNoticeReturnStep2";
}
/**
* 模具扫描页面跳转

53
src/main/java/com/heai/modules/app/controller/TransferNoticeReturnPdaController.java

@ -0,0 +1,53 @@
package com.heai.modules.app.controller;
import com.heai.common.annotation.RepeatSubmit;
import com.heai.common.utils.R;
import com.heai.modules.app.entity.TransferNoticeReturnConfirmData;
import com.heai.modules.app.entity.TransferNoticeReturnLineData;
import com.heai.modules.app.entity.TransferNoticeReturnScanResult;
import com.heai.modules.app.entity.TransferNoticeReturnValidateData;
import com.heai.modules.app.service.TransferNoticeReturnPdaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* PDA 扫入库通知单退库 - rqrq
*/
@RestController
@RequestMapping("/pda/transferNoticeReturn")
public class TransferNoticeReturnPdaController {
@Autowired
private TransferNoticeReturnPdaService transferNoticeReturnPdaService;
/**
* 步骤1:扫描入库通知单 - rqrq
*/
@PostMapping("/resolveNotice")
public R resolveNotice(@RequestBody TransferNoticeReturnScanResult data) {
String transFerNo = data == null ? "" : data.getTransFerNo();
return R.ok().put("row", transferNoticeReturnPdaService.resolveNotice(transFerNo));
}
/**
* 步骤2:扫袋贴校验 - rqrq
*/
@PostMapping("/validateBagLine")
public R validateBagLine(@RequestBody TransferNoticeReturnValidateData data) {
TransferNoticeReturnLineData line = transferNoticeReturnPdaService.validateBagLine(data);
return R.ok().put("row", line);
}
/**
* 确认退库 - rqrq
*/
@PostMapping("/confirm")
@RepeatSubmit
public R confirm(@RequestBody TransferNoticeReturnConfirmData data) {
transferNoticeReturnPdaService.confirm(data);
return R.ok("操作成功!");
}
}

36
src/main/java/com/heai/modules/app/dao/TransferNoticeReturnDao.java

@ -0,0 +1,36 @@
package com.heai.modules.app.dao;
import com.heai.modules.app.entity.TransferNoticeReturnNoticeRow;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 扫入库通知单退库查询与回写 - rqrq
*/
@Mapper
public interface TransferNoticeReturnDao {
/**
* 按通知单号取头和明细 - rqrq
*/
List<TransferNoticeReturnNoticeRow> listNoticeDetail(@Param("transNo") String transNo);
/**
* 按 ConfirmedTransNo 取该张 SR 的入库批次、仓库、库位 - rqrq
*/
TransferNoticeReturnNoticeRow getInboundByConfirmedTransNo(@Param("site") String site,
@Param("transNo") String transNo,
@Param("partNo") String partNo);
/**
* 通知单头改为已取消,仅当前仍是已入库时更新 - rqrq
*/
int cancelNoticeHeader(@Param("transNo") String transNo, @Param("site") String site);
/**
* 通知单明细 ConfirmQty 置 0 - rqrq
*/
int resetNoticeConfirmQty(@Param("transNo") String transNo, @Param("site") String site);
}

18
src/main/java/com/heai/modules/app/entity/TransferNoticeReturnConfirmData.java

@ -0,0 +1,18 @@
package com.heai.modules.app.entity;
import lombok.Data;
import java.util.List;
/**
* PDA 扫入库通知单退库 - 确认 - rqrq
*/
@Data
public class TransferNoticeReturnConfirmData {
private String transFerNo;
private List<TransferNoticeReturnLineData> lines;
private String operatorUserName;
}

32
src/main/java/com/heai/modules/app/entity/TransferNoticeReturnLineData.java

@ -0,0 +1,32 @@
package com.heai.modules.app.entity;
import lombok.Data;
/**
* PDA 扫入库通知单退库 - 表格行 - rqrq
*/
@Data
public class TransferNoticeReturnLineData {
private Long labelRecordId;
private String partNo;
private String qtyIssue;
private String batchNo;
private String locationId;
private String partDescSpec;
private String umid;
private String warehouseId;
private String wareHouseName;
private String itemNo;
private String qtyReady;
}

36
src/main/java/com/heai/modules/app/entity/TransferNoticeReturnNoticeRow.java

@ -0,0 +1,36 @@
package com.heai.modules.app.entity;
import lombok.Data;
import java.math.BigDecimal;
/**
* 扫入库通知单退库:通知单头、明细及对应 SR 批次 - rqrq
*/
@Data
public class TransferNoticeReturnNoticeRow {
private String transNo;
private String site;
private String noticeStatus;
private String confirmedTransNo;
private String orderNo;
private String partNo;
private String partDescription;
private Integer seqNo;
private BigDecimal confirmQty;
private String batchNo;
private String inboundLocationId;
private String inboundWarehouseId;
}

32
src/main/java/com/heai/modules/app/entity/TransferNoticeReturnScanResult.java

@ -0,0 +1,32 @@
package com.heai.modules.app.entity;
import lombok.Data;
/**
* PDA 扫入库通知单退库 - 步骤1返回 - rqrq
*/
@Data
public class TransferNoticeReturnScanResult {
private String site;
private String orderNo;
private String partNo;
private String partDescription;
/** 生产订单状态 - rqrq */
private String status;
private Integer seqNo;
/** 入库通知单号 - rqrq */
private String transFerNo;
/** 通知单已入库数量 - rqrq */
private String confirmQty;
/** 该通知单 SR 入库批次 - rqrq */
private String noticeBatchNo;
}

14
src/main/java/com/heai/modules/app/entity/TransferNoticeReturnValidateData.java

@ -0,0 +1,14 @@
package com.heai.modules.app.entity;
import lombok.Data;
/**
* PDA 扫入库通知单退库 - 袋贴校验 - rqrq
*/
@Data
public class TransferNoticeReturnValidateData {
private String qrContent;
private String transFerNo;
}

38
src/main/java/com/heai/modules/app/service/TransferNoticeReturnPdaService.java

@ -0,0 +1,38 @@
package com.heai.modules.app.service;
import com.heai.modules.app.entity.TransferNoticeReturnConfirmData;
import com.heai.modules.app.entity.TransferNoticeReturnLineData;
import com.heai.modules.app.entity.TransferNoticeReturnScanResult;
import com.heai.modules.app.entity.TransferNoticeReturnValidateData;
/**
* PDA 扫入库通知单退库 - rqrq
*/
public interface TransferNoticeReturnPdaService {
/**
* @Description 扫描入库通知单,带出派工单和生产订单 - rqrq
* @param transFerNo 入库通知单号
* @return 步骤1展示数据
* @author rqrq
* @date 2026/11/04
*/
TransferNoticeReturnScanResult resolveNotice(String transFerNo);
/**
* @Description 扫描袋贴,校验批次、派工单和整袋库存 - rqrq
* @param data 通知单号和袋贴内容
* @return 可加入表格的一行
* @author rqrq
* @date 2026/11/04
*/
TransferNoticeReturnLineData validateBagLine(TransferNoticeReturnValidateData data);
/**
* @Description 数量核对后执行退库,并关闭入库通知单 - rqrq
* @param data 通知单号和袋贴行
* @author rqrq
* @date 2026/11/04
*/
void confirm(TransferNoticeReturnConfirmData data);
}

563
src/main/java/com/heai/modules/app/service/impl/TransferNoticeReturnPdaServiceImpl.java

@ -0,0 +1,563 @@
package com.heai.modules.app.service.impl;
import com.heai.common.utils.DateUtil;
import com.heai.modules.app.dao.InventoryStockDao;
import com.heai.modules.app.dao.TransferNoticeReturnDao;
import com.heai.modules.app.entity.InventoryStockData;
import com.heai.modules.app.entity.TransferNoticeReturnConfirmData;
import com.heai.modules.app.entity.TransferNoticeReturnLineData;
import com.heai.modules.app.entity.TransferNoticeReturnNoticeRow;
import com.heai.modules.app.entity.TransferNoticeReturnScanResult;
import com.heai.modules.app.entity.TransferNoticeReturnValidateData;
import com.heai.modules.app.service.TransferNoticeReturnPdaService;
import com.heai.modules.app.service.WareHouseService;
import com.heai.modules.production.dao.FunctionMapper;
import com.heai.modules.production.entity.ChangeLocationData;
import com.heai.modules.production.entity.DailyPlanInData;
import com.heai.modules.production.entity.PrintLabelRecord;
import com.heai.modules.production.entity.ShopOrderData;
import com.heai.modules.production.service.DailyPlanService;
import com.heai.modules.production.service.PrintLabelRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* PDA 扫入库通知单退库:按通知单关联的 SR 校验批次,退库后关闭通知单 - rqrq
*
* @author rqrq
*/
@Slf4j
@Service
public class TransferNoticeReturnPdaServiceImpl implements TransferNoticeReturnPdaService {
private static final String TRANS_TYPE_SRR = "SRR";
private static final String COST_GROUP_EMPTY = "";
private static final String ORDER_REF_EMPTY = "";
private static final String ALLOW_NEGATIVE_N = "N";
private static final String PARTNER_ID_STAR = "*";
private static final String STATUS_IN_STOCK = "已入库";
private static final String NOTICE_STATUS_IN = "已入库";
private static final String NOTICE_STATUS_ENTERED = "已录入";
private static final String NOTICE_STATUS_CANCEL = "已取消";
private static final BigDecimal QTY_GAP_RATE = new BigDecimal("0.02");
private static final String QTY_MISMATCH_MSG = "退库数量与入库通知单数量不符";
@Autowired
private TransferNoticeReturnDao transferNoticeReturnDao;
@Autowired
private InventoryStockDao inventoryStockDao;
@Autowired
private WareHouseService wareHouseService;
@Autowired
private FunctionMapper functionMapper;
@Autowired
private DailyPlanService dailyPlanService;
@Autowired
private PrintLabelRecordService printLabelRecordService;
/**
* @Description 扫描入库通知单 - rqrq
*/
@Override
public TransferNoticeReturnScanResult resolveNotice(String transFerNo) {
LoadedNotice loaded = loadNotice(transFerNo);
TransferNoticeReturnScanResult result = new TransferNoticeReturnScanResult();
result.setSite(loaded.notice.getSite());
result.setOrderNo(loaded.shop.getOrderNo());
result.setPartNo(loaded.notice.getPartNo());
result.setPartDescription(loaded.notice.getPartDescription());
result.setStatus(loaded.shop.getStatus());
result.setSeqNo(loaded.notice.getSeqNo());
result.setTransFerNo(loaded.notice.getTransNo());
result.setConfirmQty(toPlainQtyString(loaded.notice.getConfirmQty()));
result.setNoticeBatchNo(trim(loaded.inbound.getBatchNo()));
log.info("入库通知单退库-步骤1 - rqrq,transNo={},orderNo={},batch={}",
result.getTransFerNo(), result.getOrderNo(), result.getNoticeBatchNo());
return result;
}
/**
* @Description 扫描袋贴校验 - rqrq
*/
@Override
public TransferNoticeReturnLineData validateBagLine(TransferNoticeReturnValidateData data) {
if (data == null || !StringUtils.hasText(data.getQrContent())) {
throw new RuntimeException("请扫描袋装标签");
}
LoadedNotice loaded = loadNotice(data.getTransFerNo());
ParsedBagQr qr = parseBagQr(data.getQrContent());
PrintLabelRecord bag = loadBag(qr);
assertBagBelongsToNotice(bag, loaded);
InventoryStockData stock = loadStock(loaded, bag);
BigDecimal printQty = assertBagStock(bag, stock);
TransferNoticeReturnLineData line = new TransferNoticeReturnLineData();
line.setLabelRecordId(bag.getId());
fillLine(line, stock, bag, printQty);
log.info("入库通知单退库-袋贴校验通过 - rqrq,transNo={},labelId={},batch={}",
loaded.notice.getTransNo(), bag.getId(), bag.getBatchNo());
return line;
}
/**
* @Description 确认退库并关闭通知单 - rqrq
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void confirm(TransferNoticeReturnConfirmData data) {
if (data == null) {
throw new RuntimeException("参数不能为空");
}
if (!StringUtils.hasText(data.getOperatorUserName())) {
throw new RuntimeException("无法获取登录用户");
}
List<TransferNoticeReturnLineData> lines = data.getLines();
if (lines == null || lines.isEmpty()) {
throw new RuntimeException("没有退库明细");
}
LoadedNotice loaded = loadNotice(data.getTransFerNo());
String userName = trim(data.getOperatorUserName());
String site = loaded.notice.getSite();
String orderNo = loaded.shop.getOrderNo();
Set<Long> labelSeen = new HashSet<Long>();
List<ReadyLine> readyList = new ArrayList<ReadyLine>();
BigDecimal returnQty = BigDecimal.ZERO;
for (int i = 0; i < lines.size(); i++) {
TransferNoticeReturnLineData line = lines.get(i);
int rowNo = i + 1;
if (line.getLabelRecordId() == null) {
throw new RuntimeException("第" + rowNo + "行缺少袋装标签标识");
}
if (!labelSeen.add(line.getLabelRecordId())) {
throw new RuntimeException("第" + rowNo + "行:袋装标签重复");
}
PrintLabelRecord bag = printLabelRecordService.getById(line.getLabelRecordId());
assertBagBasics(bag);
assertBagBelongsToNotice(bag, loaded);
if (!StringUtils.hasText(line.getPartNo()) || !eqIgnoreCase(line.getPartNo(), bag.getPartNo())) {
throw new RuntimeException("第" + rowNo + "行料号与标签不一致");
}
if (!StringUtils.hasText(line.getBatchNo()) || !trim(line.getBatchNo()).equals(trim(bag.getBatchNo()))) {
throw new RuntimeException("第" + rowNo + "行批号与标签不一致");
}
BigDecimal qtyFromLine = parseQty(line.getQtyIssue(), rowNo);
BigDecimal printQty = bag.getPrintQty();
if (printQty == null || printQty.compareTo(qtyFromLine) != 0) {
throw new RuntimeException("第" + rowNo + "行退库数量须等于标签整袋数量");
}
InventoryStockData stock = loadStock(loaded, bag);
assertReturnQtyAgainstOnHand(rowNo, printQty, stock);
ReadyLine ready = new ReadyLine();
ready.bag = bag;
ready.qty = printQty;
readyList.add(ready);
returnQty = returnQty.add(printQty);
}
assertQtyNearConfirm(returnQty, loaded.notice.getConfirmQty());
List<OutLine> outRows = new ArrayList<OutLine>();
Set<String> warehouses = new HashSet<String>();
for (int i = 0; i < readyList.size(); i++) {
ReadyLine ready = readyList.get(i);
PrintLabelRecord bag = ready.bag;
boolean needRelocate = needRelocate(bag.getWarehouseId(), bag.getLocationId(),
loaded.inbound.getInboundWarehouseId(), loaded.inbound.getInboundLocationId());
if (needRelocate) {
ChangeLocationData mv = new ChangeLocationData();
mv.setSite(site);
mv.setPartNo(trim(bag.getPartNo()));
mv.setQty(ready.qty.doubleValue());
mv.setBatchNo(trim(bag.getBatchNo()));
mv.setLocationId(normLoc(bag.getLocationId()));
mv.setWarehouseId(trim(bag.getWarehouseId()));
mv.setNewLocationId(normLoc(loaded.inbound.getInboundLocationId()));
mv.setNewWareHouseId(trim(loaded.inbound.getInboundWarehouseId()));
mv.setUserId(userName);
mv.setPrintQty(1.0);
mv.setPrintLabelId(null);
wareHouseService.saveChangeLocationIdNoPrintLabel(Collections.singletonList(mv));
log.info("入库通知单退库-已移回原始库位 - rqrq,partNo={},目标仓={},目标位={}",
bag.getPartNo(), loaded.inbound.getInboundWarehouseId(), loaded.inbound.getInboundLocationId());
}
OutLine out = new OutLine();
out.warehouseId = trim(loaded.inbound.getInboundWarehouseId());
out.partNo = trim(bag.getPartNo());
out.batchNo = trim(bag.getBatchNo());
out.locationId = normLoc(loaded.inbound.getInboundLocationId());
out.qty = ready.qty.doubleValue();
outRows.add(out);
warehouses.add(out.warehouseId);
}
if (warehouses.size() != 1) {
throw new RuntimeException("本次退库包含多个仓库,请拆分为多次提交");
}
String warehouse0 = outRows.get(0).warehouseId;
if (!StringUtils.hasText(warehouse0)) {
throw new RuntimeException("入库主档仓库为空,无法退库");
}
saveReturnTrans(site, warehouse0, userName, orderNo, outRows);
for (ReadyLine ready : readyList) {
inventoryStockDao.updatePrintLabelAfterBagOtherOut(ready.bag.getId());
}
int headerRows = transferNoticeReturnDao.cancelNoticeHeader(loaded.notice.getTransNo(), site);
if (headerRows != 1) {
throw new RuntimeException("入库通知单状态已变化,请重新扫描");
}
int detailRows = transferNoticeReturnDao.resetNoticeConfirmQty(loaded.notice.getTransNo(), site);
if (detailRows < 1) {
throw new RuntimeException("入库通知单明细更新失败");
}
log.info("入库通知单退库完成 - rqrq,transNo={},orderNo={},行数={}",
loaded.notice.getTransNo(), orderNo, readyList.size());
}
/**
* 读取已入库通知单、派工单和生产入库批次 - rqrq
*/
private LoadedNotice loadNotice(String transFerNo) {
if (!StringUtils.hasText(transFerNo)) {
throw new RuntimeException("请输入入库通知单号");
}
List<TransferNoticeReturnNoticeRow> rows = transferNoticeReturnDao.listNoticeDetail(trim(transFerNo));
if (rows == null || rows.isEmpty()) {
throw new RuntimeException("入库通知单不存在");
}
if (rows.size() != 1) {
throw new RuntimeException("入库通知单明细不唯一");
}
TransferNoticeReturnNoticeRow notice = rows.get(0);
String noticeStatus = trim(notice.getNoticeStatus());
if (NOTICE_STATUS_CANCEL.equals(noticeStatus)) {
throw new RuntimeException("该入库通知单已取消");
}
// 没收满时状态仍是已录入,但 ConfirmQty 已经大于 0,也允许退库 - rqrq
if (!NOTICE_STATUS_IN.equals(noticeStatus) && !NOTICE_STATUS_ENTERED.equals(noticeStatus)) {
throw new RuntimeException("该入库通知单不是已入库状态");
}
if (notice.getSeqNo() == null) {
throw new RuntimeException("该入库通知单没有派工单号");
}
if (!StringUtils.hasText(notice.getConfirmedTransNo())) {
throw new RuntimeException("该入库通知单未关联入库单");
}
if (notice.getConfirmQty() == null || notice.getConfirmQty().compareTo(BigDecimal.ZERO) <= 0) {
throw new RuntimeException("该入库通知单没有入库数量");
}
TransferNoticeReturnNoticeRow inbound = transferNoticeReturnDao.getInboundByConfirmedTransNo(
trim(notice.getSite()), trim(notice.getConfirmedTransNo()), trim(notice.getPartNo()));
if (inbound == null || !StringUtils.hasText(inbound.getBatchNo())) {
throw new RuntimeException("该入库通知单未找到对应入库批次");
}
if (!StringUtils.hasText(inbound.getInboundWarehouseId()) || !StringUtils.hasText(inbound.getInboundLocationId())) {
throw new RuntimeException("该入库通知单的入库仓库或库位为空");
}
DailyPlanInData dispatch = new DailyPlanInData();
dispatch.setSeqNo(notice.getSeqNo());
ShopOrderData shop = dailyPlanService.getShopOrderForReturn(dispatch);
if (shop == null || !StringUtils.hasText(shop.getOrderNo())) {
throw new RuntimeException("根据通知单派工单未找到生产订单");
}
if (isForbiddenReturnStatus(shop.getStatus())) {
throw new RuntimeException("该生产订单状态不允许生产退库,请检查生产订单状态");
}
if (!eqIgnoreCase(shop.getSite(), notice.getSite())) {
throw new RuntimeException("通知单工厂与派工单工厂不一致");
}
if (!eqIgnoreCase(shop.getOrderNo(), notice.getOrderNo())) {
throw new RuntimeException("通知单生产订单与派工单不一致");
}
if (!eqIgnoreCase(shop.getPartNo(), notice.getPartNo())) {
throw new RuntimeException("通知单物料与生产订单物料不一致");
}
LoadedNotice loaded = new LoadedNotice();
loaded.notice = notice;
loaded.inbound = inbound;
loaded.shop = shop;
return loaded;
}
private PrintLabelRecord loadBag(ParsedBagQr qr) {
PrintLabelRecord bag = inventoryStockDao.selectPrintLabelBagBySeqNoAndItemNo(qr.seqNo, qr.itemNo);
assertBagBasics(bag);
if (!eqIgnoreCase(qr.site, bag.getSite())) {
throw new RuntimeException("扫码工厂与标签记录不一致");
}
if (!eqIgnoreCase(qr.partNo, bag.getPartNo())) {
throw new RuntimeException("扫码物料与标签记录不一致");
}
return bag;
}
private void assertBagBelongsToNotice(PrintLabelRecord bag, LoadedNotice loaded) {
if (!eqIgnoreCase(bag.getSite(), loaded.notice.getSite())) {
throw new RuntimeException("袋贴工厂与入库通知单不一致");
}
if (!eqIgnoreCase(bag.getPartNo(), loaded.notice.getPartNo())) {
throw new RuntimeException("该袋贴物料与入库通知单不一致");
}
if (bag.getSeqNo() == null || bag.getSeqNo().longValue() != loaded.notice.getSeqNo().longValue()) {
throw new RuntimeException("该袋贴派工单与入库通知单不一致");
}
if (!trim(bag.getBatchNo()).equals(trim(loaded.inbound.getBatchNo()))) {
throw new RuntimeException("袋贴批次错误,该通知单的批次应该是" + trim(loaded.inbound.getBatchNo()));
}
}
private InventoryStockData loadStock(LoadedNotice loaded, PrintLabelRecord bag) {
InventoryStockData query = new InventoryStockData();
query.setSite(trim(bag.getSite()));
query.setWarehouseId(trim(bag.getWarehouseId()));
query.setPartNo(trim(bag.getPartNo()));
query.setBatchNo(trim(bag.getBatchNo()));
query.setLocationId(normLoc(bag.getLocationId()));
query.setOrderNo(trim(loaded.shop.getOrderNo()));
query.setSeqNo(loaded.notice.getSeqNo());
return inventoryStockDao.getInventoryStockData(query);
}
private BigDecimal assertBagStock(PrintLabelRecord bag, InventoryStockData stock) {
if (stock == null || !StringUtils.hasText(stock.getSite())) {
throw new RuntimeException("仓库无此物料批次或标签与账存不一致");
}
BigDecimal onHand = stock.getQtyOnHand() == null ? BigDecimal.ZERO : stock.getQtyOnHand();
if (onHand.compareTo(BigDecimal.ZERO) <= 0) {
throw new RuntimeException("该库位现存量不足");
}
BigDecimal printQty = bag.getPrintQty();
if (printQty == null || printQty.compareTo(BigDecimal.ZERO) <= 0) {
throw new RuntimeException("标签打印数量无效");
}
if (onHand.compareTo(printQty) < 0) {
throw new RuntimeException("现存量不足以整袋退库(需 " + toPlainQtyString(printQty) + ",现存量 " + toPlainQtyString(onHand) + ")");
}
return printQty;
}
private static void assertReturnQtyAgainstOnHand(int rowNo, BigDecimal qtyLine, InventoryStockData stock) {
if (stock == null || !StringUtils.hasText(stock.getSite())) {
throw new RuntimeException("第" + rowNo + "行:当前库位不存在该库存批次");
}
BigDecimal onHand = stock.getQtyOnHand() == null ? BigDecimal.ZERO : stock.getQtyOnHand();
if (onHand.compareTo(BigDecimal.ZERO) <= 0) {
throw new RuntimeException("第" + rowNo + "行:该库位现存数量不足");
}
if (qtyLine.compareTo(onHand) > 0) {
throw new RuntimeException("第" + rowNo + "行:退库数量超过库位现存数量");
}
}
/**
* 袋贴合计与通知单 ConfirmQty 相差达到 2% 则拒绝,提示不写比例 - rqrq
*/
private static void assertQtyNearConfirm(BigDecimal returnQty, BigDecimal confirmQty) {
if (returnQty == null || confirmQty == null || confirmQty.compareTo(BigDecimal.ZERO) <= 0) {
throw new RuntimeException(QTY_MISMATCH_MSG);
}
BigDecimal diff = returnQty.subtract(confirmQty).abs();
BigDecimal limit = confirmQty.multiply(QTY_GAP_RATE);
if (diff.compareTo(limit) >= 0) {
throw new RuntimeException(QTY_MISMATCH_MSG);
}
}
private void assertBagBasics(PrintLabelRecord bag) {
if (bag == null || bag.getId() == null) {
throw new RuntimeException("袋装标签不存在");
}
if (!STATUS_IN_STOCK.equals(trim(bag.getStatus()))) {
throw new RuntimeException("标签状态不是已入库,不能退库");
}
if (!StringUtils.hasText(bag.getWarehouseId()) || !StringUtils.hasText(bag.getLocationId())
|| !StringUtils.hasText(bag.getBatchNo())) {
throw new RuntimeException("标签未绑定仓库/库位/批号,不能退库");
}
}
private void fillLine(TransferNoticeReturnLineData line, InventoryStockData stock, PrintLabelRecord bag, BigDecimal printQty) {
line.setWarehouseId(trim(bag.getWarehouseId()));
line.setWareHouseName(stock.getWareHouseName() != null ? stock.getWareHouseName() : "");
line.setPartNo(trim(bag.getPartNo()));
line.setQtyIssue(toPlainQtyString(printQty));
line.setBatchNo(trim(bag.getBatchNo()));
line.setLocationId(normLoc(bag.getLocationId()));
line.setPartDescSpec(stock.getPartNoDescSpec() != null ? stock.getPartNoDescSpec() : "");
line.setUmid("");
line.setItemNo(bag.getItemNo() == null ? "" : String.valueOf(bag.getItemNo()));
line.setQtyReady("");
}
private static ParsedBagQr parseBagQr(String raw) {
String[] parts = raw.split(";", -1);
if (parts.length != 5 && parts.length != 6) {
throw new RuntimeException("袋装标签格式错误,应为:site;partNo;数量;seqNo;item_no");
}
for (int i = 0; i < parts.length; i++) {
parts[i] = parts[i] == null ? "" : parts[i].trim();
}
long seq;
long item;
try {
seq = Long.parseLong(parts[3]);
item = Long.parseLong(parts[4]);
} catch (NumberFormatException e) {
throw new RuntimeException("袋装标签序号或项次格式错误");
}
if (seq <= 0 || item <= 0) {
throw new RuntimeException("袋装标签序号或项次无效");
}
if (!StringUtils.hasText(parts[0]) || !StringUtils.hasText(parts[1])) {
throw new RuntimeException("袋装标签缺少工厂或物料");
}
ParsedBagQr qr = new ParsedBagQr();
qr.site = parts[0];
qr.partNo = parts[1];
qr.seqNo = seq;
qr.itemNo = item;
return qr;
}
private void saveReturnTrans(String site, String warehouseId, String userName, String orderNo, List<OutLine> outRows) {
Date transDate;
try {
transDate = DateUtil.getDate(DateUtil.getStringDate(new Date()));
} catch (ParseException e) {
throw new RuntimeException("业务日期解析失败");
}
List<Object> headerParams = new ArrayList<Object>();
headerParams.add(trim(site));
headerParams.add(trim(warehouseId));
headerParams.add(TRANS_TYPE_SRR);
headerParams.add(transDate);
headerParams.add(trim(userName));
headerParams.add(trim(userName));
headerParams.add("");
headerParams.add(PARTNER_ID_STAR);
headerParams.add("入库通知单退库");
headerParams.add(orderNo);
headerParams.add("");
Map<String, Object> map = functionMapper.getProcedure("Inventory_Create_TransHeader_other", headerParams);
if (map == null) {
throw new RuntimeException("主档存储过程无返回");
}
String resultCode = String.valueOf(map.get("result_code")).trim();
String transNo = String.valueOf(map.get("result_msg")).trim();
if (!"200".equals(resultCode)) {
throw new RuntimeException(transNo);
}
if (!StringUtils.hasText(transNo)) {
throw new RuntimeException("未生成退库出库单号");
}
for (int i = 0; i < outRows.size(); i++) {
OutLine row = outRows.get(i);
List<Object> detailParams = new ArrayList<Object>();
detailParams.add(trim(site));
detailParams.add(transNo);
detailParams.add(i + 1);
detailParams.add(row.partNo);
detailParams.add(row.batchNo);
detailParams.add(row.locationId.toUpperCase());
detailParams.add(row.qty);
detailParams.add(COST_GROUP_EMPTY);
detailParams.add(trim(orderNo));
detailParams.add(ORDER_REF_EMPTY);
detailParams.add(ORDER_REF_EMPTY);
detailParams.add(ALLOW_NEGATIVE_N);
map = functionMapper.getProcedure("Inventory_Create_TransDetail_Out_other", detailParams);
if (map == null) {
throw new RuntimeException("明细存储过程无返回:" + row.partNo);
}
String detailCode = String.valueOf(map.get("result_code")).trim();
if (!"200".equals(detailCode)) {
throw new RuntimeException(String.valueOf(map.get("result_msg")));
}
}
}
private static BigDecimal parseQty(String qtyStr, int rowNo) {
if (!StringUtils.hasText(qtyStr)) {
throw new RuntimeException("第" + rowNo + "行退库数量无效");
}
try {
BigDecimal value = new BigDecimal(trim(qtyStr));
if (value.compareTo(BigDecimal.ZERO) <= 0) {
throw new RuntimeException("第" + rowNo + "行退库数量须大于 0");
}
return value;
} catch (NumberFormatException e) {
throw new RuntimeException("第" + rowNo + "行退库数量格式错误");
}
}
private static boolean needRelocate(String labelWh, String labelLoc, String inboundWh, String inboundLoc) {
return !eqIgnoreCase(labelWh, inboundWh) || !Objects.equals(normLoc(labelLoc), normLoc(inboundLoc));
}
private static boolean isForbiddenReturnStatus(String status) {
if (!StringUtils.hasText(status)) {
return false;
}
String value = status.trim();
return "已计划".equals(value) || "已取消".equals(value) || "已关闭".equals(value);
}
private static boolean eqIgnoreCase(String left, String right) {
return trim(left).equalsIgnoreCase(trim(right));
}
private static String toPlainQtyString(BigDecimal qty) {
return qty.stripTrailingZeros().toPlainString();
}
private static String normLoc(String value) {
return value == null ? "" : value.trim().toUpperCase();
}
private static String trim(String value) {
return value == null ? "" : value.trim();
}
private static final class ParsedBagQr {
private String site;
private String partNo;
private long seqNo;
private long itemNo;
}
private static final class LoadedNotice {
private TransferNoticeReturnNoticeRow notice;
private TransferNoticeReturnNoticeRow inbound;
private ShopOrderData shop;
}
private static final class ReadyLine {
private PrintLabelRecord bag;
private BigDecimal qty;
}
private static final class OutLine {
private String warehouseId;
private String partNo;
private String batchNo;
private String locationId;
private double qty;
}
}

55
src/main/resources/mapper/app/TransferNoticeReturn.xml

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.heai.modules.app.dao.TransferNoticeReturnDao">
<!-- rqrq - 入库通知单头和明细 -->
<select id="listNoticeDetail" resultType="com.heai.modules.app.entity.TransferNoticeReturnNoticeRow">
SELECT h.TransNo AS transNo,
h.Site AS site,
h.Status AS noticeStatus,
h.ConfirmedTransNo AS confirmedTransNo,
d.OrderNo AS orderNo,
d.PartNo AS partNo,
(SELECT TOP 1 p.PartDescription FROM Part p WHERE p.Site = h.Site AND p.PartNo = d.PartNo) AS partDescription,
d.seqNo AS seqNo,
CAST(d.ConfirmQty AS decimal(18, 4)) AS confirmQty
FROM SOOpsTransferHeader h
INNER JOIN SOOpsTransferDetail d ON h.TransNo = d.TransNo AND h.Site = d.Site
WHERE h.TransNo = #{transNo,jdbcType=VARCHAR}
</select>
<!-- rqrq - 通知单关联的那张 SR -->
<select id="getInboundByConfirmedTransNo" resultType="com.heai.modules.app.entity.TransferNoticeReturnNoticeRow">
SELECT TOP 1
d.TransNo AS transNo,
d.Site AS site,
d.PartNo AS partNo,
d.BatchNo AS batchNo,
d.LocationID AS inboundLocationId,
h.WarehouseID AS inboundWarehouseId
FROM TransDetail d
INNER JOIN TransHeader h ON h.Site = d.Site AND h.TransNo = d.TransNo
WHERE d.Site = #{site,jdbcType=VARCHAR}
AND d.TransNo = #{transNo,jdbcType=VARCHAR}
AND d.PartNo = #{partNo,jdbcType=VARCHAR}
AND d.Direction = '+'
ORDER BY d.ItemNo
</select>
<!-- rqrq - 退库成功后关闭通知单 -->
<update id="cancelNoticeHeader">
UPDATE SOOpsTransferHeader
SET Status = N'已取消'
WHERE TransNo = #{transNo,jdbcType=VARCHAR}
AND Site = #{site,jdbcType=VARCHAR}
AND Status IN (N'已入库', N'已录入')
</update>
<!-- rqrq - 退库成功后清已入库数量 -->
<update id="resetNoticeConfirmQty">
UPDATE SOOpsTransferDetail
SET ConfirmQty = 0
WHERE TransNo = #{transNo,jdbcType=VARCHAR}
AND Site = #{site,jdbcType=VARCHAR}
</update>
</mapper>

137
src/main/resources/static/js/pdaOther/transferNoticeReturnStep1.js

@ -0,0 +1,137 @@
/**
* PDA 扫入库通知单退库 - 步骤1 - rqrq
*/
var titleName = $("#current_titleName").val();
var currentData = null;
var COOKIE_ORDER = "noticeRetPdaOrder";
var COOKIE_TABLE = "noticeRetPdaTable";
function clearOrderCookie () {
$.cookie(COOKIE_ORDER, "", { expires: -1, path: "/" });
$.cookie(COOKIE_ORDER, "", { expires: -1 });
}
function clearTableCookie () {
$.cookie(COOKIE_TABLE, "", { expires: -1, path: "/" });
$.cookie(COOKIE_TABLE, "", { expires: -1 });
}
function clearNoticeReturnCookies () {
clearOrderCookie();
clearTableCookie();
}
function readOrderCookieSafe () {
var saved = $.cookie(COOKIE_ORDER);
if (saved == null || saved === "") {
return null;
}
try {
return JSON.parse(saved);
} catch (e) {
clearOrderCookie();
return null;
}
}
$(function () {
if (titleName != null && titleName !== "") {
$("#titleName").text(titleName);
} else {
window.location.href = "/login";
}
currentData = readOrderCookieSafe();
if (currentData != null) {
initVal();
clearOrderCookie();
}
$("#orderNo_search").focus();
});
$("#orderNo_search").bind("keydown", function (event) {
if (event.keyCode === 13) {
getOrderNoData();
}
});
function getOrderNoData () {
var raw = ($("#orderNo_search").val() || "").trim();
if (raw === "") {
layer.msg("请输入入库通知单号!");
return false;
}
$.ajax({
url: "/pda/transferNoticeReturn/resolveNotice",
contentType: "application/json",
type: "POST",
data: JSON.stringify({ transFerNo: raw }),
dataType: "JSON",
beforeSend: function (request) {
request.setRequestHeader("token", $.cookie("token"));
},
success: function (data) {
if (data.code === 0) {
if (data.row && data.row.orderNo != null && data.row.orderNo !== "") {
currentData = data.row;
if (currentData.status === "已计划" || currentData.status === "已取消" || currentData.status === "已关闭") {
currentData = null;
layer.msg("该生产订单状态不允许生产退库,请检查生产订单状态");
return false;
}
clearTableCookie();
initVal();
} else {
layer.msg("入库通知单号错误!");
}
} else {
layer.msg(data.msg || "查询失败");
}
},
error: function (data) {
showHttpError(data);
}
});
}
function initVal () {
$("#transFerNo").val(currentData.transFerNo);
$("#site").val(currentData.site);
$("#orderNo").val(currentData.orderNo);
$("#seqNo").val(currentData.seqNo);
$("#partNo").val(currentData.partNo);
$("#partDescription").val(currentData.partDescription);
$("#status").val(currentData.status);
$("#confirmQty").val(currentData.confirmQty);
$("#noticeBatchNo").val(currentData.noticeBatchNo);
}
function pageJump () {
if (currentData == null || !currentData.transFerNo) {
layer.msg("请先扫描入库通知单!");
return false;
}
$.cookie(COOKIE_ORDER, JSON.stringify(currentData), { path: "/" });
var menuId = $("#menuId").val();
var superiorName = $("#current_titleName").val();
window.location.href = "/pdaOther/transferNoticeReturnStep2?menuId=" + encodeURIComponent(menuId || "") + "&titleName=" + encodeURIComponent(superiorName || "");
}
function pdaBaseJump () {
clearNoticeReturnCookies();
window.location.href = "/pda/pdaBase";
}
function showHttpError (data) {
var responseText = data.responseText;
var json_str = JSON.parse(responseText);
var status = json_str.status;
var message = json_str.message;
if (403 === status) {
layer.alert(message, function () {
window.location.href = "/login";
});
}
layer.closeAll("loading");
}

279
src/main/resources/static/js/pdaOther/transferNoticeReturnStep2.js

@ -0,0 +1,279 @@
/**
* PDA 扫入库通知单退库 - 步骤2 - rqrq
*/
var titleName = $("#current_titleName").val();
var currentData = null;
var tableList = [];
var confirmSubmitting = false;
var COOKIE_ORDER = "noticeRetPdaOrder";
var COOKIE_TABLE = "noticeRetPdaTable";
function clearOrderCookie () {
$.cookie(COOKIE_ORDER, "", { expires: -1, path: "/" });
$.cookie(COOKIE_ORDER, "", { expires: -1 });
}
function clearTableCookie () {
$.cookie(COOKIE_TABLE, "", { expires: -1, path: "/" });
$.cookie(COOKIE_TABLE, "", { expires: -1 });
}
function clearNoticeReturnCookies () {
clearOrderCookie();
clearTableCookie();
}
function readJsonCookieSafe (cookieName, clearFn) {
var raw = $.cookie(cookieName);
if (raw == null || raw === "") {
return null;
}
try {
return JSON.parse(raw);
} catch (e) {
if (clearFn) {
clearFn();
}
return null;
}
}
function bagLabelDupKey (seqNo, itemNo) {
return String(seqNo) + "_" + String(itemNo);
}
function showCheckMessage (msg) {
if (msg && msg.indexOf("袋贴批次错误") === 0) {
layer.alert(msg);
return;
}
layer.msg(msg || "校验失败");
}
$(function () {
if (titleName != null && titleName !== "") {
$("#titleName").text(titleName);
} else {
window.location.href = "/login";
}
var orderCookie = readJsonCookieSafe(COOKIE_ORDER, clearOrderCookie);
if (orderCookie != null && orderCookie.transFerNo) {
currentData = orderCookie;
} else {
clearNoticeReturnCookies();
layer.msg("请先扫描入库通知单");
goStep1();
return;
}
var list = readJsonCookieSafe(COOKIE_TABLE, clearTableCookie);
if (Array.isArray(list)) {
tableList = list;
changeTable();
}
$("#partNo_search").focus();
});
function changeTable () {
var str = "";
if (tableList.length > 0) {
$("#wareHouse").val(tableList[0].warehouseId + "-" + (tableList[0].wareHouseName || ""));
} else {
$("#wareHouse").val("");
}
for (var i = 0; i < tableList.length; i++) {
str += "<tr id='bagRow_" + tableList[i].labelRecordId + "'>" +
'<th style="text-align:center;background-color: #ffff;width: 20%;"><span>' + tableList[i].partNo + "</span></th>" +
'<th style="text-align:center;background-color: #ffff;width: 20%;"><span>' + tableList[i].qtyIssue + "</span></th>" +
'<th style="text-align:center;background-color: #ffff;width: 39%;"><span>' + tableList[i].batchNo + "</span></th>" +
'<th style="text-align:center;background-color: #ffff;width: 20%;"><span>' + tableList[i].locationId + "</span></th>" +
"</tr>";
}
$("#issue_table").html("").append(str);
$.cookie(COOKIE_TABLE, JSON.stringify(tableList), { path: "/" });
}
$("#partNo_search").bind("keydown", function (event) {
if (event.keyCode === 13) {
queryPart();
}
});
function appendRowFromValidated (row, labelDupKey) {
if (!row || !row.partNo || row.labelRecordId == null) {
layer.msg("校验返回数据无效");
return;
}
if (labelDupKey != null && tableList.some(function (item) { return item.labelDupKey === labelDupKey; })) {
layer.msg("该袋装标签已在本单扫描过,请勿重复扫码");
return;
}
if (tableList.some(function (item) { return item.labelRecordId === row.labelRecordId; })) {
layer.msg("该袋装标签已在本单扫描过,请勿重复扫码");
return;
}
if (tableList.length > 0 && row.warehouseId !== tableList[0].warehouseId) {
layer.msg("仓库编码与首张标签不一致!");
return;
}
tableList.push({
partNo: row.partNo,
qtyIssue: String(row.qtyIssue),
batchNo: row.batchNo,
locationId: row.locationId,
partDescSpec: row.partDescSpec != null ? row.partDescSpec : "",
umid: row.umid != null ? row.umid : "",
warehouseId: row.warehouseId,
wareHouseName: row.wareHouseName != null ? row.wareHouseName : "",
qtyReady: row.qtyReady != null ? row.qtyReady : "",
itemNo: row.itemNo != null ? row.itemNo : "",
labelRecordId: row.labelRecordId,
labelDupKey: labelDupKey
});
changeTable();
$("#partNo_search").val("").focus();
}
function queryPart () {
var raw = $("#partNo_search").val();
if (raw == null || raw === "") {
layer.msg("请扫描袋装标签!");
return false;
}
var segs = raw.split(";").map(function (item) { return (item || "").trim(); });
if (segs.length !== 5 && segs.length !== 6) {
layer.msg("袋装标签格式错误!");
return false;
}
if (currentData == null || !currentData.transFerNo) {
layer.msg("缺少入库通知单,请返回上一步");
return false;
}
var seqNoParsed = Number(segs[3]);
var itemNoParsed = Number(segs[4]);
if (!isFinite(seqNoParsed) || !isFinite(itemNoParsed) || seqNoParsed <= 0 || itemNoParsed <= 0) {
layer.msg("袋装标签序号或项次无效");
return false;
}
var dupKey = bagLabelDupKey(Math.floor(seqNoParsed), Math.floor(itemNoParsed));
if (tableList.some(function (item) { return item.labelDupKey === dupKey; })) {
layer.msg("该袋装标签已在本单扫描过,请勿重复扫码");
return false;
}
$.ajax({
url: "/pda/transferNoticeReturn/validateBagLine",
contentType: "application/json",
type: "POST",
data: JSON.stringify({
qrContent: raw,
transFerNo: currentData.transFerNo
}),
dataType: "JSON",
beforeSend: function (request) {
request.setRequestHeader("token", $.cookie("token"));
},
success: function (data) {
if (data.code === 0) {
appendRowFromValidated(data.row, dupKey);
} else {
showCheckMessage(data.msg);
}
},
error: function (data) {
showHttpError(data);
}
});
}
function confirmReturn () {
if (confirmSubmitting) {
return false;
}
if (tableList.length === 0) {
layer.msg("请扫描袋装标签并添加退库行!");
return false;
}
var body = {
transFerNo: currentData.transFerNo,
operatorUserName: $("#current_username").val(),
lines: tableList.map(function (item) {
return {
labelRecordId: item.labelRecordId,
partNo: item.partNo,
qtyIssue: String(item.qtyIssue),
batchNo: item.batchNo,
locationId: item.locationId,
partDescSpec: item.partDescSpec,
umid: item.umid,
warehouseId: item.warehouseId,
wareHouseName: item.wareHouseName,
itemNo: item.itemNo,
qtyReady: item.qtyReady
};
})
};
confirmSubmitting = true;
$.ajax({
url: "/pda/transferNoticeReturn/confirm",
contentType: "application/json",
type: "POST",
data: JSON.stringify(body),
dataType: "JSON",
beforeSend: function (request) {
request.setRequestHeader("token", $.cookie("token"));
},
success: function (data) {
if (data.code === 0) {
layer.msg(data.msg || "操作成功!");
clearNoticeReturnCookies();
tableList = [];
currentData = null;
changeTable();
setTimeout(function () {
goStep1();
}, 600);
} else {
showCheckMessage(data.msg);
}
},
error: function (data) {
showHttpError(data);
},
complete: function () {
confirmSubmitting = false;
}
});
}
function superiorJump () {
$.cookie(COOKIE_TABLE, JSON.stringify(tableList), { path: "/" });
$.cookie(COOKIE_ORDER, JSON.stringify(currentData), { path: "/" });
goStep1();
}
function pdaBaseJump () {
clearNoticeReturnCookies();
window.location.href = "/pda/pdaBase";
}
function goStep1 () {
var menuId = $("#menuId").val();
var superiorName = $("#current_titleName").val();
window.location.href = "/pdaOther/productionBagReturnStep1?menuId=" + encodeURIComponent(menuId || "") + "&titleName=" + encodeURIComponent(superiorName || "");
}
function showHttpError (data) {
var responseText = data.responseText;
var json_str = JSON.parse(responseText);
var status = json_str.status;
var message = json_str.message;
if (403 === status) {
layer.alert(message, function () {
window.location.href = "/login";
});
}
layer.closeAll("loading");
}

152
src/main/resources/templates/pdaOther/transferNoticeReturnStep1.ftl

@ -0,0 +1,152 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="/favicon.ico">
<title>${project_title!"赫艾Pda"}</title>
<link rel="stylesheet" type="text/css" href="/js/bootstrap-3.3.7/css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="/js/bootstrap-3.3.7/css/bootstrap-select.css">
<link href="/css/base1.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="/css/button.css">
<link href="/js/layer/skin/layer.css" rel="stylesheet">
<style type="text/css">
.form-input-2 {
width: 80%;
height: 25px;
padding: 3px 3px;
font-size: 12px;
line-height: 1.42857143;
color: #555;
background-image: none;
border: 1px solid #ccc;
border-radius: 4px;
text-align: left;
float: left;
margin-left: -11px;
}
.ivu-form-item {
margin-left: 30px;
margin-top: -16px;
}
</style>
</head>
<div class="hideData" style="display: none;">
<#if user ??>
<input id="current_id" value="${user.userId ! ''}">
<input id="current_username" value="${user.username!'' }">
<input id="current_email" value="${user.email!'' }">
<input id="current_mobile" value="${user.mobile!'' }">
<input id="current_site" value="${user.site!'' }">
<input id="current_languageDefault" value="${user.languageDefault!'' }">
<input id="menuId" value="${menuId!'' }">
<input id="current_titleName" value="${titleName!'' }">
</#if>
</div>
<body>
<div id="app">
<header class="mint-header is-fixed">
<div class="mint-header-button is-left">
<div class="header-title">
<a href="javascript:void(0);" class="go-back" onclick="pdaBaseJump()"><i class="mintui mintui-back"></i></a>
<span id = "titleName"></span>
</div>
</div>
<h1 class="mint-header-title"></h1>
<div class="mint-header-button is-right"></div>
</header>
<div autocomplete="off" style="margin-left: 27px;width: 90px;height: 24px;margin-top: -10px;">
<label class="ivu-form-item-label" >入库通知单</label>
</div>
<div autocomplete="off" style="width: 260px;margin-left: 25px;height: 24px;margin-top: -5px;">
<input id="orderNo_search" type="text" class="form-input-2" >
</div>
<div autocomplete="off" style="margin-top: -24px;width: 48px;margin-left: 230px;">
<button class="btn btn-primary" style="padding: 1px 8px;font-size: 12px;height: 24px;width: 44px;" onclick="getOrderNoData()">查询</button>
</div>
<div autocomplete="off" style="margin-left: 27px;width: 72px;height: 24px;margin-top: 5px;">
<label class="ivu-form-item-label" >通知单号</label>
</div>
<div autocomplete="off" style="width: 260px;margin-left: 25px;height: 24px;margin-top: -5px;">
<input id="transFerNo" type="text" class="form-input-2" readonly>
</div>
<div autocomplete="off" style="margin-left: 27px;width: 48px;height: 24px;margin-top: 5px;">
<label class="ivu-form-item-label" >工厂编号</label>
</div>
<div autocomplete="off" style="width: 260px;margin-left: 25px;height: 24px;margin-top: -5px;">
<input id="site" type="text" class="form-input-2" readonly>
</div>
<div autocomplete="off" style="margin-left: 27px;width: 60px;height: 24px;margin-top: 5px;">
<label class="ivu-form-item-label" >生产订单号</label>
</div>
<div autocomplete="off" style="width: 260px;margin-left: 25px;height: 24px;margin-top: -5px;">
<input id="orderNo" type="text" class="form-input-2" readonly>
</div>
<div autocomplete="off" style="margin-left: 27px;width: 60px;height: 24px;margin-top: 5px;">
<label class="ivu-form-item-label" >派工单号</label>
</div>
<div autocomplete="off" style="width: 260px;margin-left: 25px;height: 24px;margin-top: -5px;">
<input id="seqNo" type="text" class="form-input-2" readonly>
</div>
<div autocomplete="off" style="margin-left: 28px;width: 48px;height: 24px;margin-top: 5px;">
<label class="ivu-form-item-label" >产品编码</label>
</div>
<div autocomplete="off" style="width: 260px;margin-left: 25px;height: 24px;margin-top: -5px;">
<input id="partNo" type="text" class="form-input-2" readonly>
</div>
<div autocomplete="off" style="margin-left: 28px;width: 48px;height: 24px;margin-top: 5px;">
<label class="ivu-form-item-label" >产品名称</label>
</div>
<div autocomplete="off" style="width: 260px;margin-left: 25px;height: 24px;margin-top: -5px;">
<input id="partDescription" type="text" class="form-input-2" readonly>
</div>
<div autocomplete="off" style="margin-left: 28px;width: 48px;height: 24px;margin-top: 5px;">
<label class="ivu-form-item-label" >订单状态</label>
</div>
<div autocomplete="off" style="width: 260px;margin-left: 25px;height: 24px;margin-top: -5px;">
<input id="status" type="text" class="form-input-2" readonly>
</div>
<div autocomplete="off" style="margin-left: 28px;width: 60px;height: 24px;margin-top: 5px;">
<label class="ivu-form-item-label" >入库数量</label>
</div>
<div autocomplete="off" style="width: 260px;margin-left: 25px;height: 24px;margin-top: -5px;">
<input id="confirmQty" type="text" class="form-input-2" readonly>
</div>
<div autocomplete="off" style="margin-left: 28px;width: 72px;height: 24px;margin-top: 5px;">
<label class="ivu-form-item-label" >通知单批次</label>
</div>
<div autocomplete="off" style="width: 260px;margin-left: 25px;height: 24px;margin-top: -5px;">
<input id="noticeBatchNo" type="text" class="form-input-2" readonly>
</div>
<div autocomplete="off" style="margin-top: 20px;width: 120px;margin-left: 90px;">
<button class="btn btn-primary" style="padding: 1px 8px;font-size: 12px;height: 24px;width: 44px;" onclick="pdaBaseJump()">退出</button>
<button class="btn btn-primary" style="padding: 1px 8px;font-size: 12px;height: 24px;width: 55px;margin-left: 10%" onclick="pageJump()">下一步</button>
</div>
</div>
</body>
<script type="text/javascript" src="/js/jquery/jquery-2.1.4.js"></script>
<script type="text/javascript" src="/js/jquery/jquery.cookie.js"></script>
<script type="text/javascript" src="/js/bootstrap-3.3.7/js/bootstrap.js"></script>
<script type="text/javascript" src="/js/bootstrap-3.3.7/js/bootstrap-select.js"></script>
<script type="text/javascript" src="/js/layer/layer.js"></script>
<script type="text/javascript" src="/js/pdaOther/transferNoticeReturnStep1.js"></script>
</html>

120
src/main/resources/templates/pdaOther/transferNoticeReturnStep2.ftl

@ -0,0 +1,120 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="/favicon.ico">
<title>${project_title!"赫艾Pda"}</title>
<link rel="stylesheet" type="text/css" href="/js/bootstrap-3.3.7/css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="/js/bootstrap-3.3.7/css/bootstrap-select.css">
<link href="/css/base1.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="/css/button.css">
<link href="/js/layer/skin/layer.css" rel="stylesheet">
<style type="text/css">
.form-input-2 {
width: 80%;
height: 25px;
padding: 3px 3px;
font-size: 12px;
line-height: 1.42857143;
color: #555;
background-image: none;
border: 1px solid #ccc;
border-radius: 4px;
text-align: left;
float: left;
margin-left: -11px;
}
.ivu-form-item {
margin-left: 30px;
margin-top: -16px;
}
</style>
</head>
<div class="hideData" style="display: none;">
<#if user ??>
<input id="current_id" value="${user.userId ! ''}">
<input id="current_username" value="${user.username!'' }">
<input id="current_email" value="${user.email!'' }">
<input id="current_mobile" value="${user.mobile!'' }">
<input id="current_site" value="${user.site!'' }">
<input id="current_languageDefault" value="${user.languageDefault!'' }">
<input id="menuId" value="${menuId!'' }">
<input id="current_titleName" value="${titleName!'' }">
</#if>
</div>
<body>
<div id="app">
<header class="mint-header is-fixed">
<div class="mint-header-button is-left">
<div class="header-title">
<a href="javascript:void(0);" class="go-back" onclick="pdaBaseJump()"><i class="mintui mintui-back"></i></a>
<span id = "titleName"></span>
</div>
</div>
<h1 class="mint-header-title"></h1>
<div class="mint-header-button is-right"></div>
</header>
<div autocomplete="off" style="margin-left: 15px;width: 132px;height: 24px;margin-top: -10px;">
<label class="ivu-form-item-label" >请扫描袋装标签</label>
</div>
<div autocomplete="off" style="width: 260px;margin-left: 25px;height: 24px;margin-top: -5px;">
<input id="partNo_search" type="text" class="form-input-2" >
</div>
<div autocomplete="off" style="margin-top: -24px;width: 48px;margin-left: 230px;">
<button class="btn btn-primary" style="padding: 1px 8px;font-size: 12px;height: 24px;width: 44px;" onclick="queryPart()">查询</button>
</div>
<div autocomplete="off" style="margin-left: 27px;width: 48px;height: 24px;margin-top: 5px;">
<label class="ivu-form-item-label" >物料仓库</label>
</div>
<div autocomplete="off" style="width: 260px;margin-left: 25px;height: 24px;margin-top: -5px;">
<input id="wareHouse" disabled type="text" class="form-input-2" >
</div>
<div class="ivu-row" style="margin-top: 10px;">
<div class="ivu-table-wrapper">
<div class="ivu-table" style="font-size: 11px;">
<div class="ivu-table-header">
<table style="width: 100%;" cellspacing="0" cellpadding="0" border="0">
<thead>
<tr>
<th class="" style="text-align:center;width: 20%;"><span>物料编码</span></th>
<th class="" style="text-align:center;width: 20%;"><span>退库数量</span></th>
<th class="" style="text-align:center;width: 39%;"><span>批号</span></th>
<th class="" style="text-align:center;width: 20%;"><span>库位</span></th>
</tr>
</thead>
</table>
</div>
<div class="ivu-table-body" style="overflow-y: visible">
<table style="width: 100%;" cellspacing="0" cellpadding="0" border="0">
<tbody class="ivu-table-tbody" id = "issue_table" >
</tbody>
</table>
</div>
</div>
</div>
</div>
<div autocomplete="off" style="margin-top: 20px;width: 200px;margin-left: 70px;">
<button class="btn btn-primary" style="padding: 1px 8px;font-size: 12px;height: 24px;width: 55px;" onclick="superiorJump()">上一步</button>
<button class="btn btn-primary" style="padding: 1px 8px;font-size: 12px;height: 24px;width: 55px;margin-left: 10%;" onclick="confirmReturn()">确认</button>
</div>
</div>
</body>
<script type="text/javascript" src="/js/jquery/jquery-2.1.4.js"></script>
<script type="text/javascript" src="/js/jquery/jquery.cookie.js"></script>
<script type="text/javascript" src="/js/bootstrap-3.3.7/js/bootstrap.js"></script>
<script type="text/javascript" src="/js/bootstrap-3.3.7/js/bootstrap-select.js"></script>
<script type="text/javascript" src="/js/layer/layer.js"></script>
<script type="text/javascript" src="/js/pdaOther/transferNoticeReturnStep2.js"></script>
</html>
Loading…
Cancel
Save