Browse Source

Merge remote-tracking branch 'origin/master'

master
常熟吴彦祖 10 months ago
parent
commit
83a1b347e4
  1. 22
      src/main/java/com/gaotao/modules/inspection/controller/InspectionInboundController.java
  2. 24
      src/main/java/com/gaotao/modules/inspection/service/InspectionInboundService.java
  3. 587
      src/main/java/com/gaotao/modules/inspection/service/impl/InspectionInboundServiceImpl.java
  4. 2
      src/main/java/com/gaotao/modules/inspection/service/impl/QualifiedStorageServiceImpl.java
  5. 15
      src/main/java/com/gaotao/modules/po/service/impl/PoServiceImpl.java
  6. 2
      src/main/java/com/gaotao/modules/trans/entity/TransDetailDto.java

22
src/main/java/com/gaotao/modules/inspection/controller/InspectionInboundController.java

@ -22,24 +22,6 @@ public class InspectionInboundController extends AbstractController {
@Autowired
private InspectionInboundService inspectionInboundService;
/**
* 获取检验合格待入库单据列表
*/
@PostMapping("getQualifiedInspectionList")
public R getQualifiedInspectionList(@RequestBody QualifiedInspectionDto qualifiedInspectionDto) {
List<QualifiedInspectionDto> list = inspectionInboundService.getQualifiedInspectionList(qualifiedInspectionDto);
return R.ok().put("rows", list);
}
/**
* 确认检验合格入库
*/
@PostMapping("confirmQualifiedInbound")
public R confirmQualifiedInbound(@RequestBody InboundConfirmDto inboundConfirm) {
inspectionInboundService.confirmQualifiedInbound(inboundConfirm);
return R.ok();
}
/**
* 获取检验不合格待处理单据列表
*/
@ -66,8 +48,8 @@ public class InspectionInboundController extends AbstractController {
String transNo = (String) params.get("transNo");
String processType = (String) params.get("processType");
List<String> handlingUnitIds = (List<String>) params.get("handlingUnitIds");
inspectionInboundService.confirmUnqualifiedProcess(transNo, processType, handlingUnitIds);
String site = (String) params.get("site");
inspectionInboundService.confirmUnqualifiedProcess(site,transNo, processType, handlingUnitIds);
return R.ok();
}
}

24
src/main/java/com/gaotao/modules/inspection/service/InspectionInboundService.java

@ -7,34 +7,20 @@ import com.gaotao.modules.inspection.entity.InboundConfirmDto;
import java.util.List;
public interface InspectionInboundService {
/**
* 获取检验合格待入库单据列表
*/
List<QualifiedInspectionDto> getQualifiedInspectionList(QualifiedInspectionDto qualifiedInspectionDto);
/**
* 获取检验不合格待处理单据列表
*/
List<UnqualifiedInspectionDto> getUnqualifiedInspectionList(UnqualifiedInspectionDto unqualifiedInspectionDto);
/**
* 从IFS获取检验不合格待处理单据列表
*/
List<UnqualifiedInspectionDto> getUnqualifiedInspectionListFromIfs(UnqualifiedInspectionDto unqualifiedInspectionDto);
/**
* 确认检验合格入库
*/
void confirmQualifiedInbound(InboundConfirmDto inboundConfirm);
/**
* 获取入库历史记录
*/
List<QualifiedInspectionDto> getInboundHistory(QualifiedInspectionDto qualifiedInspectionDto);
/**
* 确认不合格处理
*/
void confirmUnqualifiedProcess(String transNo, String processType, List<String> handlingUnitIds);
void confirmUnqualifiedProcess(String site,String transNo, String processType, List<String> handlingUnitIds);
}

587
src/main/java/com/gaotao/modules/inspection/service/impl/InspectionInboundServiceImpl.java

@ -53,6 +53,9 @@ public class InspectionInboundServiceImpl implements InspectionInboundService {
@Autowired
private TransDetailService transDetailService;
@Autowired
private TransDetailSubService transDetailSubService;
@Autowired
private InventoryStockMapper inventoryStockMapper;
@ -69,267 +72,10 @@ public class InspectionInboundServiceImpl implements InspectionInboundService {
@Autowired
private HandlingUnitService handlingUnitService;
@Value("${custom.ifs-url}")
private String ifsUrl;
@Value("${custom.ifs-ifsDBName}")
private String ifsDBName;
@Value("${custom.ifs-domainUserID}")
private String domainUserID;
@Value("${ldap-control.control-flag:false}")
private Boolean ldapFlag;
@Autowired
private IfsInspectionHistoryService ifsInspectionHistoryService;
/**
* 获取当前用户的域控账号如果开启了域控账号则获取用户的域控账号否则使用配置的默认值
*/
private String getCurrentDomainUserID() {
if (ldapFlag) {
try {
SysUserEntity currentUser = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
if (currentUser != null && StringUtils.isNotBlank(currentUser.getDomainAccount())) {
return currentUser.getDomainAccount();
}
} catch (Exception e) {
// 如果获取当前用户失败使用默认配置
}
}
return domainUserID;
}
@Override
public List<QualifiedInspectionDto> getQualifiedInspectionList(QualifiedInspectionDto qualifiedInspectionDto) {
// 直接查询po_receipt_detail表中状态为ARRIVED的记录
QueryWrapper<PoReceiptDetail> detailWrapper = new QueryWrapper<>();
detailWrapper.eq("status", "ARRIVED"); // 状态为已到货
if (qualifiedInspectionDto.getSite() != null) {
detailWrapper.eq("site", qualifiedInspectionDto.getSite());
}
// 支持根据接收单号或采购单号查找
if (qualifiedInspectionDto.getTransNo() != null) {
detailWrapper.and(wrapper -> wrapper
.eq("receipt_no", qualifiedInspectionDto.getTransNo()) // 接收单号
.or()
.eq("order_no", qualifiedInspectionDto.getTransNo()) // 采购单号
);
}
detailWrapper.orderByDesc("receipt_no");
List<PoReceiptDetail> details = poReceiptDetailService.list(detailWrapper);
List<QualifiedInspectionDto> result = new ArrayList<>();
for (PoReceiptDetail detail : details) {
// 获取对应的接收单主记录
QueryWrapper<PoReceipt> receiptWrapper = new QueryWrapper<>();
receiptWrapper.eq("site", detail.getSite());
receiptWrapper.eq("receipt_no", detail.getReceiptNo());
PoReceipt receipt = poReceiptService.getOne(receiptWrapper);
if (receipt != null) {
QualifiedInspectionDto dto = new QualifiedInspectionDto();
dto.setSite(detail.getSite());
dto.setTransNo(detail.getReceiptNo()); // 使用接收单号作为事务号
dto.setItemNo(String.valueOf(detail.getItemNo()));
dto.setPartNo(detail.getPartNo());
dto.setPartDesc(detail.getPartDesc());
dto.setTransQty(detail.getArriveQty());
dto.setQualifiedQty(detail.getQtyToInspect()); // 待检验数量
dto.setBatchNo(detail.getBatchNo());
dto.setLocationId(detail.getLocationId());
dto.setWarehouseId(receipt.getWarehouseId());
dto.setOrderRef1(detail.getOrderNo()); // 采购单号
dto.setOrderRef2("");
dto.setOrderRef3("");
dto.setTransDate(receipt.getReceiveDate());
dto.setInspectionDate(detail.getInspectionTime());
dto.setInspectionUser(detail.getInspector());
dto.setStatus("A"); // ARRIVED状态
dto.setUserName(receipt.getReceiver());
dto.setRemark(receipt.getRemark());
result.add(dto);
}
}
return result;
}
@Override
@Transactional
public void confirmQualifiedInbound(InboundConfirmDto inboundConfirm) {
try {
SysUserEntity currentUser = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
// 1. 获取采购接收单信息
PoReceipt poReceipt = poReceiptService.lambdaQuery()
.eq(PoReceipt::getSite, inboundConfirm.getSite())
.eq(PoReceipt::getReceiptNo, inboundConfirm.getTransNo())
.one();
if (poReceipt == null) {
throw new RuntimeException("采购接收单不存在: " + inboundConfirm.getTransNo());
}
// 2. 获取采购接收单明细
PoReceiptDetail poReceiptDetail = poReceiptDetailService.lambdaQuery()
.eq(PoReceiptDetail::getSite, inboundConfirm.getSite())
.eq(PoReceiptDetail::getReceiptNo, inboundConfirm.getTransNo())
.eq(PoReceiptDetail::getItemNo, Double.valueOf(inboundConfirm.getItemNo()))
.one();
if (poReceiptDetail == null) {
throw new RuntimeException("采购接收单明细不存在");
}
// 3. 创建入库事务头记录
TransNoControl transNoControl = transNoControlService.getTransNo(inboundConfirm.getSite(), "INB", 12);
String inboundTransNo = transNoControl.getNewTransNo();
TransHeader inboundHeader = new TransHeader();
inboundHeader.setSite(inboundConfirm.getSite());
inboundHeader.setTransNo(inboundTransNo);
inboundHeader.setTransDate(inboundConfirm.getInboundDate());
inboundHeader.setTransTypeDb("INB"); // 检验合格入库
inboundHeader.setWarehouseId(poReceipt.getWarehouseId());
inboundHeader.setUserId(currentUser.getUserId().toString());
inboundHeader.setUserName(currentUser.getUserDisplay());
inboundHeader.setRemark("检验合格入库 - 接收单号: " + inboundConfirm.getTransNo());
inboundHeader.setOrderRef1(poReceiptDetail.getOrderNo()); // PO号
inboundHeader.setStatus("COMPLETED");
inboundHeader.setStatusDb("C");
inboundHeader.setEnterDate(new Date());
inboundHeader.setIfsFlag("N");
transHeaderService.save(inboundHeader);
// 4. 创建入库事务明细记录
TransDetail inboundDetail = new TransDetail();
inboundDetail.setSite(inboundConfirm.getSite());
inboundDetail.setTransNo(inboundTransNo);
inboundDetail.setItemNo(Double.valueOf(inboundConfirm.getItemNo()));
inboundDetail.setPartNo(poReceiptDetail.getPartNo());
inboundDetail.setTransQty(inboundConfirm.getInboundQty());
inboundDetail.setBatchNo(poReceiptDetail.getBatchNo());
inboundDetail.setLocationId(inboundConfirm.getTargetLocationId());
inboundDetail.setDirection("+"); // 入库方向
inboundDetail.setOrderRef1(poReceipt.getOrderref1()); // PO号
inboundDetail.setOrderRef2(inboundConfirm.getTransNo()); // 接收单号
inboundDetail.setOrderRef3("");
inboundDetail.setOrderRef4("");
inboundDetail.setOrderRef5("");
inboundDetail.setRemark("检验合格入库");
transDetailService.save(inboundDetail);
// 5. 根据接收记录查找HU根据HU的数量来决定sub的数量
// HandlingUnit的orderRef2就是接收单号可以根据site+orderRef2来查HU数量
List<HandlingUnit> handlingUnits = handlingUnitService.getHandlingUnitsBySiteAndOrderRef2(
inboundConfirm.getSite(), inboundConfirm.getTransNo());
if (handlingUnits != null && !handlingUnits.isEmpty()) {
// 根据HU数量创建对应数量的TransDetailSub记录
for (int i = 0; i < handlingUnits.size(); i++) {
HandlingUnit hu = handlingUnits.get(i);
TransDetailSub transDetailSub = new TransDetailSub();
transDetailSub.setSite(inboundConfirm.getSite());
transDetailSub.setTransNo(inboundTransNo);
transDetailSub.setItemNo((double) (i + 1)); // 从1开始编号
transDetailSub.setHandlingUnitId(hu.getUnitId());
transDetailSub.setSeqNo(poReceiptDetail.getItemNo());
// 每个HU的数量
transDetailSub.setSubQty(hu.getQty() != null ? hu.getQty().doubleValue() : 0.0);
transDetailSub.setOrderRef1(poReceiptDetail.getOrderNo());
transDetailSub.setOrderRef2(inboundConfirm.getTransNo()); // 接收单号
transDetailSub.setLocationId(poReceiptDetail.getLocationId());
transDetailSub.setBatchNo(poReceiptDetail.getBatchNo());
transDetailSub.setPartNo(poReceiptDetail.getPartNo());
transDetailSub.setSubNo(hu.getUnitId()); // 使用HU的unitId作为subNo
transDetailSub.setDirection("+"); // 入库方向
transDetailSub.setRemark("检验合格入库 - HU: " + hu.getUnitId());
subService.save(transDetailSub);
}
// 将HU状态更新为已入库inStockFlag = 'Y'
QueryWrapper<HandlingUnit> huWrapper = new QueryWrapper<>();
huWrapper.in("unit_id", handlingUnits.stream().map(HandlingUnit::getUnitId).toList());
HandlingUnit huUpdate = new HandlingUnit();
huUpdate.setStatus("ACTIVE"); // 设置为失效状态
huUpdate.setInStockFlag("Y");
huUpdate.setModifiedDate(new Date());
handlingUnitService.update(huUpdate, huWrapper);
}
// 6. 更新采购接收单明细的状态
poReceiptDetailService.lambdaUpdate()
.set(PoReceiptDetail::getStatus, "RECEIVED") // 检验合格
.set(PoReceiptDetail::getQtyReceived,
poReceiptDetail.getQtyReceived() == null ? inboundConfirm.getInboundQty() :
poReceiptDetail.getQtyReceived().add(inboundConfirm.getInboundQty()))
.eq(PoReceiptDetail::getSite, inboundConfirm.getSite())
.eq(PoReceiptDetail::getReceiptNo, inboundConfirm.getTransNo())
.eq(PoReceiptDetail::getItemNo, Double.valueOf(inboundConfirm.getItemNo()))
.update();
// 7. 更新库存
updateInventoryStock(inboundHeader, inboundDetail, inboundConfirm, poReceiptDetail);
// 同步ifs
syncToIFS(inboundConfirm,poReceiptDetail);
} catch (Exception e) {
throw new RuntimeException("检验合格入库失败: " + e.getMessage(), e);
}
}
/**
* 同步到IFS
*/
private void syncToIFS(InboundConfirmDto inboundConfirm,PoReceiptDetail poReceiptDetail) {
try {
Map<String, Object> params = Map.ofEntries(
Map.entry("ifsDBName", ifsDBName),
Map.entry("domainUserID", getCurrentDomainUserID()),
Map.entry("ifsSiteID", inboundConfirm.getSite()),
Map.entry("ifsReceiptSequence", Integer.parseInt(inboundConfirm.getTransNo())), // 接收单号
Map.entry("ifsSourceRef1", poReceiptDetail.getOrderNo()), // PO号
Map.entry("ifsSourceRef2", poReceiptDetail.getOrderItemNo()), // 明细行号
Map.entry("ifsSourceRef3", poReceiptDetail.getOrderReleaseNo()), // 版本号
Map.entry("ifsSourceRef4", ""), //
Map.entry("ifsReceiptNo", poReceiptDetail.getItemNo()), // 接收单号
Map.entry("ifsPartNo", inboundConfirm.getPartNo()),
Map.entry("ifsConfigurationID", "*"), // 固定为*
Map.entry("ifsLocationNo", poReceiptDetail.getLocationId()), // 原库位
Map.entry("ifsLotBatchNo", poReceiptDetail.getBatchNo()),
Map.entry("ifsNewLotBatchNo", poReceiptDetail.getBatchNo()),
Map.entry("ifsSerialNo", "*"), // 固定为*
Map.entry("ifsEngChgLevel", "1"), // 固定为1
Map.entry("ifsWDR", poReceiptDetail.getWdr()), // WDR
Map.entry("ifsToLocationNo", inboundConfirm.getTargetLocationId()), // 目标库位
Map.entry("ifsHandlingUnitID", 0), // 固定为0
Map.entry("ifsSourceQtyToMove", inboundConfirm.getInboundQty().intValue()), // 入库数量
Map.entry("ifsInQtyToMove", inboundConfirm.getInboundQty().intValue()), // 入库数量
Map.entry("ifsCatchQtyToMove", 0) // 固定为0
);
ObjectMapper objectMapper = new ObjectMapper();
String jsonBody = objectMapper.writeValueAsString(params);
String ifsResponse = HttpUtils.doPost(ifsUrl+"PurchaseOrderMoveToStockOneLocation",jsonBody,null);
log.info("同步检验合格入库接收记录到IFS,PO号: {}", poReceiptDetail.getOrderNo());
if ("IFSUpdated".equals(ifsResponse) || "\"IFSUpdated\"".equals(ifsResponse)) {
log.info("IFS同步检验合格入库成功,PO号: {}", poReceiptDetail.getOrderNo());
} else {
log.error("IFS同步检验合格入库失败,PO号: {}, 响应: {}", poReceiptDetail.getOrderNo(), ifsResponse);
// 同步失败需要回滚前面所有的数据库操作
throw new XJException("IFS同步检验合格入库失败,响应: " + ifsResponse);
}
} catch (XJException e) {
// 重新抛出业务异常确保事务回滚
throw e;
} catch (Exception e) {
log.error("IFS同步检验合格入库失败,PO号: {}, 错误: {}", poReceiptDetail.getOrderNo(), e.getMessage());
// 同步异常需要回滚前面所有的数据库操作
throw new XJException("IFS同步异常: " + e.getMessage());
}
}
@Override
public List<QualifiedInspectionDto> getInboundHistory(QualifiedInspectionDto qualifiedInspectionDto) {
@ -379,214 +125,98 @@ public class InspectionInboundServiceImpl implements InspectionInboundService {
return result;
}
/**
* 更新库存
*/
private void updateInventoryStock(TransHeader transHeader, TransDetail transDetail, InboundConfirmDto inboundConfirm, PoReceiptDetail poReceiptDetail) {
// 直接在此方法中实现库存创建逻辑使用带行锁的库存操作防止并发
String site = transDetail.getSite();
String warehouseId = transHeader.getWarehouseId();
String partNo = transDetail.getPartNo();
String batchNo = transDetail.getBatchNo();
String locationId = inboundConfirm.getTargetLocationId();
String wdr = poReceiptDetail.getWdr() != null ? poReceiptDetail.getWdr() : "*";
BigDecimal transQty = inboundConfirm.getInboundQty();
// 使用行锁查询现有库存
InventoryStock existingStock = inventoryStockMapper.selectForUpdate(site, warehouseId, partNo, batchNo, locationId, wdr);
if (existingStock != null) {
// 库存存在更新库存检验入库一般不涉及HandlingUnit
updateExistingStockForInspection(site, warehouseId, partNo, batchNo, locationId, wdr, transQty);
} else {
// 库存不存在创建新库存记录
createNewStockForInspection(site, warehouseId, partNo, batchNo, locationId, wdr, transQty, poReceiptDetail, inboundConfirm);
}
}
/**
* 更新现有库存检验入库
*/
private void updateExistingStockForInspection(String site, String warehouseId, String partNo,
String batchNo, String locationId, String wdr,
BigDecimal addQty) {
// 检验入库一般不更新HandlingUnit数量
int updateResult = inventoryStockMapper.updateStockWithoutHandlingUnit(
site, warehouseId, partNo, batchNo, locationId, wdr, addQty);
if (updateResult == 0) {
throw new XJException("库存更新失败,可能记录已被删除或修改");
}
}
/**
* 创建新库存记录检验入库
*/
private void createNewStockForInspection(String site, String warehouseId, String partNo,
String batchNo, String locationId, String wdr,
BigDecimal transQty, PoReceiptDetail poReceiptDetail,
InboundConfirmDto inboundConfirm) {
InventoryStock newStock = new InventoryStock();
newStock.setSite(site);
newStock.setWarehouseId(warehouseId);
newStock.setPartNo(partNo);
newStock.setBatchNo(batchNo);
newStock.setLocationId(locationId);
newStock.setInQty(transQty);
newStock.setInStandardValue(transQty);
newStock.setInActualValue(transQty);
newStock.setQtyOnHand(transQty);
newStock.setOutQty(BigDecimal.ZERO);
newStock.setQtyReserved(BigDecimal.ZERO);
// PoReceiptDetail 中获取制造日期和失效日期
newStock.setManufactureDate(poReceiptDetail.getManuFactureDate());
newStock.setExpiredDate(poReceiptDetail.getExpiredDate());
newStock.setFreezeFlag("N");
newStock.setFirstInDate(inboundConfirm.getInboundDate());
newStock.setLatestInDate(inboundConfirm.getInboundDate());
newStock.setActiveDate(inboundConfirm.getInboundDate());
newStock.setWdr(wdr);
// PoReceiptDetail 中获取长度和宽度
newStock.setLength(poReceiptDetail.getLength());
newStock.setWidth(poReceiptDetail.getWidth());
// 检验入库一般不设置HandlingUnitQty
int insertResult = inventoryStockMapper.insert(newStock);
if (insertResult == 0) {
throw new XJException("库存记录创建失败");
}
}
@Override
public List<UnqualifiedInspectionDto> getUnqualifiedInspectionList(UnqualifiedInspectionDto unqualifiedInspectionDto) {
// 查询po_receipt_detail表中所有不合格状态的记录
QueryWrapper<PoReceiptDetail> detailWrapper = new QueryWrapper<>();
// 查询所有不合格状态
detailWrapper.in("status", "RETCREDIT", "RETWORK", "INVSCRAP", "SCPCREDIT", "EXCHANGE", "REWORK");
if (unqualifiedInspectionDto.getSite() != null) {
detailWrapper.eq("site", unqualifiedInspectionDto.getSite());
}
// 支持根据接收单号或采购单号查找
if (unqualifiedInspectionDto.getTransNo() != null) {
detailWrapper.and(wrapper -> wrapper
.eq("receipt_no", unqualifiedInspectionDto.getTransNo()) // 接收单号
.or()
.eq("order_no", unqualifiedInspectionDto.getTransNo()) // 采购单号
);
}
detailWrapper.orderByDesc("receipt_no");
List<PoReceiptDetail> details = poReceiptDetailService.list(detailWrapper);
List<UnqualifiedInspectionDto> result = new ArrayList<>();
for (PoReceiptDetail detail : details) {
// 获取对应的接收单主记录
QueryWrapper<PoReceipt> receiptWrapper = new QueryWrapper<>();
receiptWrapper.eq("site", detail.getSite());
receiptWrapper.eq("receipt_no", detail.getReceiptNo());
PoReceipt receipt = poReceiptService.getOne(receiptWrapper);
if (receipt != null) {
String status = detail.getStatus();
String processType = mapStatusToProcessType(status);
BigDecimal unqualifiedQty = getUnqualifiedQtyByStatus(detail, status);
@Transactional
public void confirmUnqualifiedProcess(String site,String transNo, String processType, List<String> handlingUnitIds) {
try {
// 获取当前用户
SysUserEntity currentUser = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
// 只有数量大于0的记录才添加到结果中
if (unqualifiedQty != null && unqualifiedQty.compareTo(BigDecimal.ZERO) > 0) {
UnqualifiedInspectionDto dto = new UnqualifiedInspectionDto();
dto.setSite(detail.getSite());
dto.setTransNo(detail.getReceiptNo()); // 使用接收单号作为事务号
dto.setItemNo(String.valueOf(detail.getItemNo()));
dto.setPartNo(detail.getPartNo());
dto.setPartDesc(detail.getPartDesc());
dto.setTransQty(detail.getArriveQty());
dto.setUnqualifiedQty(unqualifiedQty); // 根据状态获取对应的数量
dto.setBatchNo(detail.getBatchNo());
dto.setLocationId(detail.getLocationId());
dto.setWarehouseId(receipt.getWarehouseId());
dto.setOrderRef1(detail.getOrderNo()); // 采购单号
dto.setOrderRef2("");
dto.setOrderRef3("");
dto.setTransDate(receipt.getReceiveDate());
dto.setInspectionDate(detail.getInspectionTime());
dto.setInspectionUser(detail.getInspector());
dto.setStatus(status); // 原始状态
dto.setUserName(receipt.getReceiver());
dto.setRemark(receipt.getRemark());
dto.setProcessType(processType); // 处理类型
if (handlingUnitIds != null && !handlingUnitIds.isEmpty()) {
// 1. 获取HandlingUnit信息
QueryWrapper<HandlingUnit> huQueryWrapper = new QueryWrapper<>();
huQueryWrapper.in("unit_id", handlingUnitIds);
List<HandlingUnit> handlingUnits = handlingUnitService.list(huQueryWrapper);
result.add(dto);
if (handlingUnits.isEmpty()) {
throw new RuntimeException("未找到对应的HandlingUnit记录");
}
}
}
return result;
}
/**
* 根据状态获取对应的不合格数量
*/
private BigDecimal getUnqualifiedQtyByStatus(PoReceiptDetail detail, String status) {
if (status == null) {
return BigDecimal.ZERO;
}
switch (status) {
case "RETCREDIT":
case "RETWORK":
// 退货数量
return detail.getQtyReturned() != null ? detail.getQtyReturned() : BigDecimal.ZERO;
case "INVSCRAP":
case "SCPCREDIT":
// 报废数量
return detail.getQtyScrapt()!= null ? detail.getQtyScrapt() : BigDecimal.ZERO;
case "EXCHANGE":
case "REWORK":
// 换货/返工数量 - 可能需要根据实际字段调整
return detail.getQtyReplace() != null ? detail.getQtyReplace() : BigDecimal.ZERO;
default:
return BigDecimal.ZERO;
}
}
/**
* 根据状态映射处理类型
*/
private String mapStatusToProcessType(String status) {
if (status == null) {
return "UNKNOWN";
}
switch (status) {
case "RETWORK":
return "RETURN"; // 退货
case "INVSCRAP":
case "SCPCREDIT":
return "SCRAP"; // 报废
case "EXCHANGE":
case "REWORK":
case "RETCREDIT":
return "EXCHANGE"; // 换货
default:
return "UNKNOWN";
}
}
// 计算HandlingUnit总数量
BigDecimal totalScannedQty = handlingUnits.stream()
.map(hu -> hu.getQty() != null ? hu.getQty() : BigDecimal.ZERO)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 从第一个HandlingUnit获取基本信息
HandlingUnit firstHu = handlingUnits.get(0);
String partNo = firstHu.getPartNo();
String batchNo = firstHu.getBatchNo();
String locationId = firstHu.getLocationId();
String warehouseId = "WH01"; // 默认仓库
// 2. 创建出库事务头记录
TransNoControl transNoControl = transNoControlService.getTransNo(site, "CRR", 10);
String outboundTransNo = transNoControl.getNewTransNo();
TransHeader outboundHeader = new TransHeader();
outboundHeader.setSite(site);
outboundHeader.setTransNo(outboundTransNo);
outboundHeader.setTransDate(new Date());
outboundHeader.setTransTypeDb("CRR"); // 不合格处理出库
outboundHeader.setWarehouseId(warehouseId);
outboundHeader.setUserId(currentUser.getUserId().toString());
outboundHeader.setUserName(currentUser.getUserDisplay());
outboundHeader.setRemark("不合格处理出库 - " + getProcessTypeDesc(processType) + " - 原单据: " + transNo);
outboundHeader.setOrderRef1(firstHu.getOrderNo()); // 采购单号
outboundHeader.setOrderRef2(transNo); // 原单据号
outboundHeader.setOrderRef3(processType); // 处理类型
outboundHeader.setStatus("COMPLETED");
outboundHeader.setStatusDb("C");
outboundHeader.setEnterDate(new Date());
outboundHeader.setIfsFlag("N");
transHeaderService.save(outboundHeader);
// 3. 创建出库事务明细记录
TransDetail outboundDetail = new TransDetail();
outboundDetail.setSite(site);
outboundDetail.setTransNo(outboundTransNo);
outboundDetail.setItemNo(1.0);
outboundDetail.setPartNo(partNo);
outboundDetail.setTransQty(totalScannedQty);
outboundDetail.setBatchNo(batchNo);
outboundDetail.setLocationId(locationId);
outboundDetail.setDirection("-"); // 出库方向
outboundDetail.setOrderRef1(firstHu.getOrderNo()); // 原单据号
outboundDetail.setOrderRef2(transNo);
outboundDetail.setOrderRef3(processType);
outboundDetail.setOrderRef4("");
outboundDetail.setOrderRef5("");
outboundDetail.setRemark("不合格处理出库 - " + getProcessTypeDesc(processType));
transDetailService.save(outboundDetail);
// 4. 创建HandlingUnit子记录
for (int i = 0; i < handlingUnits.size(); i++) {
HandlingUnit hu = handlingUnits.get(i);
TransDetailSub transDetailSub = new TransDetailSub();
transDetailSub.setSite(site);
transDetailSub.setTransNo(outboundTransNo);
transDetailSub.setItemNo((double) (i + 1));
transDetailSub.setSeqNo(1.0);
transDetailSub.setSubQty(hu.getQty() != null ? hu.getQty().doubleValue() : 0.0);
transDetailSub.setOrderRef1(transNo);
transDetailSub.setOrderRef2(processType);
transDetailSub.setLocationId(locationId);
transDetailSub.setBatchNo(batchNo);
transDetailSub.setPartNo(partNo);
transDetailSub.setSubNo(hu.getUnitId());
transDetailSub.setDirection("-");
transDetailSub.setRemark("不合格处理出库 - " + getProcessTypeDesc(processType) + " - HU: " + hu.getUnitId());
transDetailSubService.save(transDetailSub);
}
@Override
@Transactional
public void confirmUnqualifiedProcess(String transNo, String processType, List<String> handlingUnitIds) {
try {
// 1. 更新HandlingUnit状态为失效
if (handlingUnitIds != null && !handlingUnitIds.isEmpty()) {
// 6. 更新HandlingUnit状态
QueryWrapper<HandlingUnit> huWrapper = new QueryWrapper<>();
huWrapper.in("unit_id", handlingUnitIds);
@ -599,24 +229,11 @@ public class InspectionInboundServiceImpl implements InspectionInboundService {
if (!huResult) {
throw new RuntimeException("更新HandlingUnit状态失败");
}
}
// 2. 更新PoReceiptDetail状态为已处理
QueryWrapper<PoReceiptDetail> detailWrapper = new QueryWrapper<>();
detailWrapper.eq("receipt_no", transNo);
PoReceiptDetail detailUpdate = new PoReceiptDetail();
detailUpdate.setStatus("PROCESSED"); // 设置为已处理状态
//detailUpdate.setUpdateTime(new Date());
boolean detailResult = poReceiptDetailService.update(detailUpdate, detailWrapper);
if (!detailResult) {
throw new RuntimeException("更新接收单详情状态失败");
log.info("不合格处理确认成功 - 出库事务号: {}, 原单据号: {}, 处理类型: {}, HandlingUnit数量: {}, 总数量: {}",
outboundTransNo, transNo, processType, handlingUnits.size(), totalScannedQty);
}
log.info("不合格处理确认成功 - 单据号: {}, 处理类型: {}, HandlingUnit数量: {}",
transNo, processType, handlingUnitIds != null ? handlingUnitIds.size() : 0);
} catch (Exception e) {
log.error("确认不合格处理失败 - 单据号: {}, 错误: {}", transNo, e.getMessage(), e);
throw new RuntimeException("确认不合格处理失败: " + e.getMessage());
@ -648,7 +265,8 @@ public class InspectionInboundServiceImpl implements InspectionInboundService {
if (unqualifiedQty != null && unqualifiedQty.compareTo(BigDecimal.ZERO) > 0) {
UnqualifiedInspectionDto dto = new UnqualifiedInspectionDto();
dto.setSite(ifsHistory.getContract()); // 使用contract作为site
dto.setTransNo(ifsHistory.getOrderNo() + "-" + ifsHistory.getReceiptNo()); // 组合单据号
dto.setTransNo(ifsHistory.getOrderNo() + "-"+ifsHistory.getLineNo()+ "-"+ifsHistory.getReleaseNo()
+ "-" + ifsHistory.getReceiptNo()); // 组合单据号
dto.setItemNo(ifsHistory.getLineNo());
dto.setPartNo(ifsHistory.getSourcePartNo());
dto.setPartDesc(ifsHistory.getPartDesc());
@ -742,4 +360,25 @@ public class InspectionInboundServiceImpl implements InspectionInboundService {
return remark.toString();
}
/**
* 获取处理类型描述
*/
private String getProcessTypeDesc(String processType) {
if (processType == null) {
return "未知处理";
}
switch (processType.toUpperCase()) {
case "RETURN":
return "退货";
case "SCRAP":
return "报废";
case "EXCHANGE":
return "换货";
default:
return "未知处理";
}
}
}

2
src/main/java/com/gaotao/modules/inspection/service/impl/QualifiedStorageServiceImpl.java

@ -248,7 +248,7 @@ public class QualifiedStorageServiceImpl implements QualifiedStorageService {
}
// 2. 创建入库事务头记录
TransNoControl transNoControl = transNoControlService.getTransNo(site, "INB", 12);
TransNoControl transNoControl = transNoControlService.getTransNo(site, "INB", 10);
String inboundTransNo = transNoControl.getNewTransNo();
TransHeader inboundHeader = new TransHeader();

15
src/main/java/com/gaotao/modules/po/service/impl/PoServiceImpl.java

@ -125,11 +125,13 @@ public class PoServiceImpl extends ServiceImpl<PoMapper, PurchaseOrder> implemen
// 将Po状态放到每个行数据中
Map<String, Object> po = poData.getFirst();
String poStatus = po.get("objstate") != null ? po.get("objstate").toString() : "";
String authorizationRequired = po.get("authorizationRequired") != null ? po.get("authorizationRequired").toString() : "FALSE";
// inventoryPartDB=false需要剔除
poLineData.removeIf(line -> line.get("inventoryPartDB") != null && "false".equals(line.get("inventoryPartDB").toString()));
// 制造日期 供应商批次
for (Map<String, Object> line : poLineData) {
line.put("poStatus", poStatus);
line.put("authorizationRequired", authorizationRequired);
line.put("supplierNo", po.get("supplierNo"));
line.put("supplierName", po.get("supplierName"));
line.put("buyerCode", po.get("buyerCode"));
@ -437,6 +439,16 @@ public class PoServiceImpl extends ServiceImpl<PoMapper, PurchaseOrder> implemen
*/
private void syncToIFS(TransDetailDto inData) {
try {
BigDecimal sp = inData.getSamplePercent()!=null?new BigDecimal(inData.getSamplePercent()):BigDecimal.ZERO;
BigDecimal qtyToInspect;
if (Objects.equals(inData.getReceiveCaseDB(), "ARRINV")) {
qtyToInspect = new BigDecimal(inData.getSampleQty());
} else {
qtyToInspect = sp.compareTo(BigDecimal.ZERO)>0?
inData.getTransQty().multiply(new BigDecimal(inData.getSamplePercent())).
divide(BigDecimal.valueOf(100), 0, RoundingMode.HALF_UP):
new BigDecimal(inData.getSampleQty());
}
Map<String, Object> params = Map.ofEntries(
Map.entry("ifsDBName", ifsDBName),
Map.entry("domainUserID", getCurrentDomainUserID()),
@ -452,7 +464,8 @@ public class PoServiceImpl extends ServiceImpl<PoMapper, PurchaseOrder> implemen
Map.entry("arrivalDate", DateUtils.format(inData.getArrivalDate(), DateUtils.DATE_TIME_PATTERN)),
Map.entry("receiptReference", "Testing WMS"),
Map.entry("lotBatchNo", inData.getBatchNo()),
Map.entry("wdrNo", inData.getWdr() != null ? inData.getWdr() : "*")
Map.entry("wdrNo", inData.getWdr() != null ? inData.getWdr() : "*"),
Map.entry("qtyToInspect",qtyToInspect)
);
ObjectMapper objectMapper = new ObjectMapper();
String jsonBody = objectMapper.writeValueAsString(params);

2
src/main/java/com/gaotao/modules/trans/entity/TransDetailDto.java

@ -28,6 +28,8 @@ public class TransDetailDto extends TransDetail{
private String inventoryPartDB; // 库存物料DB
private String partDesc; // 物料描述
private String wdr; // WDR
private String samplePercent; // 抽样百分比
private String sampleQty; // 抽样数量
// 业务控制字段
private String warehouseType; // 仓库类型AUTO-立库MANUAL-普通仓库

Loading…
Cancel
Save