diff --git a/src/main/java/com/gaotao/modules/outsourcing/controller/OutsourcingReturnController.java b/src/main/java/com/gaotao/modules/outsourcing/controller/OutsourcingReturnController.java index da9cfaa..dc99cb1 100644 --- a/src/main/java/com/gaotao/modules/outsourcing/controller/OutsourcingReturnController.java +++ b/src/main/java/com/gaotao/modules/outsourcing/controller/OutsourcingReturnController.java @@ -101,8 +101,8 @@ public class OutsourcingReturnController { @PostMapping("/outsourcingReturnUnissueConfirm") public R outsourcingReturnUnissueConfirm(@RequestBody OutsourcingReturnDto dto) { try { - outsourcingReturnService.outsourcingReturnUnissueConfirm(dto); - return R.ok().put("message", "委外退料成功"); + List ids = outsourcingReturnService.outsourcingReturnUnissueConfirm(dto); + return R.ok().put("unitIds", ids); } catch (Exception e) { return R.error(e.getMessage()); } diff --git a/src/main/java/com/gaotao/modules/outsourcing/dao/OutsourcingReturnMapper.java b/src/main/java/com/gaotao/modules/outsourcing/dao/OutsourcingReturnMapper.java index 3faa48d..27ec759 100644 --- a/src/main/java/com/gaotao/modules/outsourcing/dao/OutsourcingReturnMapper.java +++ b/src/main/java/com/gaotao/modules/outsourcing/dao/OutsourcingReturnMapper.java @@ -4,10 +4,13 @@ import com.gaotao.modules.api.entity.issueAndReturnVo.InventoryPartVo; import com.gaotao.modules.api.entity.issueAndReturnVo.POLineSupplierMaterialVo; import com.gaotao.modules.handlingunit.entity.HandlingUnit; import com.gaotao.modules.outsourcing.entity.dto.MrIssueMaterialDto; +import com.gaotao.modules.production.entity.dto.CreateHuRequestReturnIssueDto; +import com.gaotao.modules.warehouse.entity.Location; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; +import java.util.Set; /** * 委外退料数据访问接口 @@ -31,4 +34,14 @@ public interface OutsourcingReturnMapper { HandlingUnit scanMaterialLabelForOutsourcing(@Param("scannedLabel") String scannedLabel, @Param("site") String site, @Param("componentPartNo") String componentPartNo); void updateHandingUnit(List list); + + List getAllLocation(@Param("site")String site); + + Location getLocation(@Param("locationId")String locationId, @Param("site")String site); + + HandlingUnit getOneHandlingUnit(@Param("request")CreateHuRequestReturnIssueDto request); + + List selectByUnitIds(Set unitIds); + + int updateNewHandingUnit(List handlingUnits); } diff --git a/src/main/java/com/gaotao/modules/outsourcing/entity/dto/MrIssueMaterialDto.java b/src/main/java/com/gaotao/modules/outsourcing/entity/dto/MrIssueMaterialDto.java index 78d7ddd..cbf48db 100644 --- a/src/main/java/com/gaotao/modules/outsourcing/entity/dto/MrIssueMaterialDto.java +++ b/src/main/java/com/gaotao/modules/outsourcing/entity/dto/MrIssueMaterialDto.java @@ -32,4 +32,6 @@ public class MrIssueMaterialDto { private String engChgLevel; private BigDecimal height; + + private String newPrint; } diff --git a/src/main/java/com/gaotao/modules/outsourcing/service/OutsourcingReturnService.java b/src/main/java/com/gaotao/modules/outsourcing/service/OutsourcingReturnService.java index 9dbf748..c784d6e 100644 --- a/src/main/java/com/gaotao/modules/outsourcing/service/OutsourcingReturnService.java +++ b/src/main/java/com/gaotao/modules/outsourcing/service/OutsourcingReturnService.java @@ -37,7 +37,7 @@ public interface OutsourcingReturnService { /** * 确认委外退料 */ - void outsourcingReturnUnissueConfirm(OutsourcingReturnDto dto) throws Exception; + List outsourcingReturnUnissueConfirm(OutsourcingReturnDto dto) throws Exception; } diff --git a/src/main/java/com/gaotao/modules/outsourcing/service/impl/OutsourcingReturnServiceImpl.java b/src/main/java/com/gaotao/modules/outsourcing/service/impl/OutsourcingReturnServiceImpl.java index 958585a..102f900 100644 --- a/src/main/java/com/gaotao/modules/outsourcing/service/impl/OutsourcingReturnServiceImpl.java +++ b/src/main/java/com/gaotao/modules/outsourcing/service/impl/OutsourcingReturnServiceImpl.java @@ -3,27 +3,36 @@ package com.gaotao.modules.outsourcing.service.impl; import com.gaotao.modules.api.entity.issueAndReturnVo.*; import com.gaotao.modules.api.service.IfsApiIssueAndReturnService; import com.gaotao.modules.handlingunit.entity.HandlingUnit; +import com.gaotao.modules.handlingunit.service.HandlingUnitIdGeneratorService; import com.gaotao.modules.handlingunit.service.HandlingUnitService; import com.gaotao.modules.outsourcing.dao.OutsourcingReturnMapper; import com.gaotao.modules.outsourcing.entity.dto.OutsourcingReturnDto; import com.gaotao.modules.outsourcing.entity.dto.MrIssueMaterialDto; import com.gaotao.modules.outsourcing.service.OutsourcingReturnService; +import com.gaotao.modules.production.entity.dto.CreateHuRequestReturnIssueDto; import com.gaotao.modules.production.entity.dto.MaterialLabelInfo; import com.gaotao.modules.production.entity.dto.WorkOrderMaterialDto; import com.gaotao.modules.trans.entity.TransCommonRequestDto; import com.gaotao.modules.trans.entity.TransCommonSubDto; import com.gaotao.modules.trans.entity.TransDetail; import com.gaotao.modules.trans.service.TransHeaderService; +import com.gaotao.modules.warehouse.entity.Location; import jakarta.transaction.Transactional; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; /** * 委外退料服务实现类 */ +@Slf4j @Service public class OutsourcingReturnServiceImpl implements OutsourcingReturnService { @@ -35,6 +44,12 @@ public class OutsourcingReturnServiceImpl implements OutsourcingReturnService { @Autowired private TransHeaderService transHeaderService; + @Autowired + private HandlingUnitService handlingUnitService; + @Autowired + private HandlingUnitIdGeneratorService handlingUnitIdGeneratorService; + @Autowired + private com.gaotao.modules.handlingunit.service.HandlingUnitIdLogService handlingUnitIdLogService; @Override public List searchOutsourcingOrdersForReturn(String searchValue, String site) throws Exception { @@ -85,11 +100,39 @@ public class OutsourcingReturnServiceImpl implements OutsourcingReturnService { @Override @Transactional - public void outsourcingReturnUnissueConfirm(OutsourcingReturnDto dto) throws Exception { + public List outsourcingReturnUnissueConfirm(OutsourcingReturnDto dto) throws Exception { if (dto.getSelectedMaterials() == null || dto.getSelectedMaterials().isEmpty()) { throw new Exception("没有选择要退料的物料"); } + validateLocal(dto.getSelectedMaterials(),dto.getSite()); + List newSelectMaterials = new ArrayList<>(); + //如果时NEW的HU,改变他的unit + for(MrIssueMaterialDto material : dto.getSelectedMaterials()){ + if("NEW".equals(material.getNewPrint())){ + CreateHuRequestReturnIssueDto huRequest = new CreateHuRequestReturnIssueDto(); + huRequest.setSite(dto.getSite()); + huRequest.setLocationId(material.getLocationId()); + huRequest.setPartNo(dto.getComponentPartNo()); + huRequest.setPartDesc(dto.getComponentPartNo()); + huRequest.setBatchNo(dto.getBatchNo()); + huRequest.setWdr(material.getWdrNo()); + huRequest.setHeight(material.getHeight()); + huRequest.setQty(material.getIssueQty()); + huRequest.setOrderNo(dto.getOutsourcingOrderNo()); + String unitId = createNewReturnHandlingUnits(huRequest); + material.setLabelCode(unitId); + newSelectMaterials.add(material); + }else{ + HandlingUnit byId = handlingUnitService.getById(material.getLabelCode()); + if(byId == null){ + throw new Exception("数据库不存在确认退料标签"); + } + material.setHeight(material.getHeight().add(byId.getHeight() == null ? BigDecimal.ZERO:byId.getHeight())); + newSelectMaterials.add(material); + } + } + List subList = new ArrayList<>(); TransCommonRequestDto transCommonRequestDto = new TransCommonRequestDto(); @@ -99,8 +142,20 @@ public class OutsourcingReturnServiceImpl implements OutsourcingReturnService { transCommonRequestDto.setRemark("委外退料-订单:" + dto.getOutsourcingOrderNo()); transCommonRequestDto.setStatus("C"); transCommonRequestDto.setWorkOrderNo(dto.getOutsourcingOrderNo()); + transCommonRequestDto.setWarehouseId(dto.getWarehouseId()); + transCommonRequestDto.setSourceNo(dto.getOutsourcingOrderNo()); Double seqNo = 1.0; + List allLocation = outsourcingReturnMapper.getAllLocation(dto.getSite()); + Map locationWarehouseMap = allLocation.stream() + .filter(loc -> loc != null + && loc.getLocationId() != null + && !loc.getLocationId().trim().isEmpty()) + .collect(Collectors.toMap( + loc -> loc.getLocationId().trim(), + Location::getWarehouseId, + (oldVal, newVal) -> newVal + )); // 处理每个选择的物料 for (MrIssueMaterialDto material : dto.getSelectedMaterials()) { // 创建退料记录详情 @@ -108,8 +163,11 @@ public class OutsourcingReturnServiceImpl implements OutsourcingReturnService { subDto.setPartNo(material.getPartNo()); subDto.setSubNo(material.getLabelCode()); subDto.setBatchNo(material.getBatchNo()); - subDto.setWarehouseId(material.getWarehouseId()); subDto.setLocationId(material.getLocationId()); + String targetWarehouseId = locationWarehouseMap.get(material.getLocationId()); + if (targetWarehouseId != null) { + subDto.setWarehouseId(targetWarehouseId); + } subDto.setTransQty(material.getIssueQty().toString()); subDto.setDirection("+"); // 退料为正向 subDto.setWdrNo(material.getWdrNo() == null ? "*" : material.getWdrNo()); @@ -122,6 +180,51 @@ public class OutsourcingReturnServiceImpl implements OutsourcingReturnService { transCommonRequestDto.setSubList(subList); List out = transHeaderService.genTransAndChangeInventoryStock(transCommonRequestDto, "IN"); + //前端打印新标签并跟新HandlingUnit的库位和长度 + List handlingUnits = new ArrayList<>(); + List unitIdPrints = new ArrayList<>(); + Set unitIds = dto.getSelectedMaterials().stream() + .map(MrIssueMaterialDto::getLabelCode) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + if (unitIds.isEmpty()) { + throw new IllegalArgumentException("列表中标签号均为空,无法查询数据库"); + } + List huList = outsourcingReturnMapper.selectByUnitIds(unitIds); + Map huMap = huList.stream() + .collect(Collectors.toMap(HandlingUnit::getUnitId, hu -> hu, (existing, replacement) -> existing)); + + for (MrIssueMaterialDto material : newSelectMaterials) { + HandlingUnit hu = new HandlingUnit(); + hu.setUnitId(material.getLabelCode()); + hu.setLocationId(material.getLocationId()); + String targetWarehouseId = locationWarehouseMap.get(material.getLocationId()); + if (targetWarehouseId != null) { + hu.setWarehouseId(targetWarehouseId); + } + if("NEW".equals(material.getNewPrint())){ + hu.setQty(material.getIssueQty()); + }else{ + String unitId = material.getLabelCode(); + if (unitId != null && huMap.containsKey(unitId)) { + //减去要出的hu上的数量 + HandlingUnit unit = huMap.get(unitId); + BigDecimal qty = unit.getQty(); + BigDecimal materialIssueQty = material.getIssueQty(); + if (qty != null && materialIssueQty != null) { + BigDecimal nowQty = qty.add(materialIssueQty).setScale(6, RoundingMode.HALF_UP); + hu.setQty(nowQty); + } + } + } + hu.setHeight(material.getHeight() == null ? BigDecimal.ZERO : material.getHeight()); + + handlingUnits.add(hu); + + unitIdPrints.add(material.getLabelCode()); + } + outsourcingReturnMapper.updateNewHandingUnit(handlingUnits); + // 同步退料到IFS系统 for (TransDetail issue : out) { PurchaseOrderUnIssueComponentDto reserveComponentDto = new PurchaseOrderUnIssueComponentDto(); @@ -142,14 +245,199 @@ public class OutsourcingReturnServiceImpl implements OutsourcingReturnService { reserveComponentDto.setIfsQty(dto.getAllQty()); // 退料 String s = ifsApiIssueAndReturnService.addPurchaseOrderUnIssueComponent(reserveComponentDto); } - List handlingUnits = new ArrayList<>(); - for (MrIssueMaterialDto material : dto.getSelectedMaterials()) { - HandlingUnit hu = new HandlingUnit(); - hu.setUnitId(material.getLabelCode()); - hu.setLocationId(material.getLocationId()); - hu.setQty(material.getIssueQty()); - handlingUnits.add(hu); + + return unitIdPrints; + } + + public boolean validateLocal(List selectedMaterials, String site) throws Exception{ + // 校验库位 + Set unitIds = selectedMaterials.stream() + .map(MrIssueMaterialDto::getLocationId) + .collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(unitIds)) { + throw new IllegalArgumentException("存在库位为输入"); + } + List allLocation = outsourcingReturnMapper.getAllLocation(site); + Set existingLocationIds = allLocation.stream() + .map(Location::getLocationId) + .filter(locationId -> locationId != null && !locationId.trim().isEmpty()) // 过滤无效值 + .map(String::trim) + .collect(Collectors.toSet()); + + // 3. 筛选出unitIds中不存在于existingLocationIds的元素 + Set nonExistentIds = unitIds.stream() + .filter(locationId -> !existingLocationIds.contains(locationId)) + .collect(Collectors.toSet()); + + // 4. 若存在不存在的locationId,抛异常(明确提示不存在的ID,方便排查) + if (!CollectionUtils.isEmpty(nonExistentIds)) { + throw new Exception( + String.format("列表中库位%s不存在", + String.join(", ", nonExistentIds)) + ); + } + + return true; + } + + @Transactional + public String createNewReturnHandlingUnits(CreateHuRequestReturnIssueDto request) throws Exception{ + + Location location = outsourcingReturnMapper.getLocation(request.getLocationId(), request.getSite()); + if(location == null){ + throw new Exception("库位不存在,请确认"); + } + + // 1. 先创建packageCount个完整HU + HandlingUnit onunit = outsourcingReturnMapper.getOneHandlingUnit(request); + List partInStock = null; + Date newReceiveDate = null; + Date newManufactureDate = null; + Date newExpireData = null; + String newUmId = request.getUmid() == null?"":request.getUmid(); + String newEngChgLevel = null; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'-'HH.mm.ss"); + if(onunit == null){ + partInStock = ifsApiIssueAndReturnService.getAnInventoryPartInStock(request.getSite(), request.getPartNo()); + if(partInStock == null || partInStock.size() == 0){ + //throw new Exception("无法获取物料信息"); + //todo 目前一些物料没有入库信息,所以使用当前时间作为入库时间 + newReceiveDate = new Date(); + newManufactureDate = new Date(); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date()); + calendar.add(Calendar.YEAR, 2); + Date datePlusTwoYears = calendar.getTime(); + newExpireData = datePlusTwoYears; + newEngChgLevel = "1"; + }else{ + for(AnInventoryPartInStockVo vo:partInStock){ + if(vo.getContract().equals(request.getSite()) && vo.getPartNo().equals(request.getPartNo()) && vo.getLotBatchNo().equals(request.getBatchNo()) && vo.getLocationNo().equals(request.getLocationId())){ + newReceiveDate = sdf.parse(vo.getReceiptDate()); + newManufactureDate = sdf.parse(vo.getReceiptDate()); + newExpireData = sdf.parse(vo.getExpirationDate()); + newEngChgLevel = vo.getEngChgLevel(); + } + } + + } + }else{ + newReceiveDate = onunit.getReceiveDate(); + newManufactureDate = onunit.getManufactureDate(); + newExpireData = onunit.getExpiredDate(); + newUmId = onunit.getUmId(); + newEngChgLevel = onunit.getEngChgLevel() != null ? onunit.getEngChgLevel() : "1"; + } + + // 生成处理单元ID + String unitId = handlingUnitIdGeneratorService.generateUnitId(request.getSite()); + + // 记录unitId生成日志到数据库 + handlingUnitIdLogService.logUnitIdGeneration( + unitId, + request.getSite(), + "IFS_INIT", + "", + "", + request.getPartNo(), + request.getBatchNo(), + request.getQty().doubleValue(), + "SYSTEM", + "GENERATING", + "IFS库存初始化-完整HU-第" + 1 + "个" + ); + + // 创建HandlingUnit对象 + HandlingUnit handlingUnit = new HandlingUnit(); + handlingUnit.setUnitId(unitId); + handlingUnit.setSite(request.getSite()); + handlingUnit.setUnitType("ROLL"); + handlingUnit.setUnitTypeDb("ROLL"); + handlingUnit.setPartNo(request.getPartNo()); + handlingUnit.setPartDesc(request.getPartDesc()); + handlingUnit.setQty(request.getQty()); // 使用计算后的数量 + handlingUnit.setBatchNo(request.getBatchNo()); + handlingUnit.setLocationId(request.getLocationId()); + handlingUnit.setWarehouseId(location.getWarehouseId()); + handlingUnit.setWdr(request.getWdr()); + handlingUnit.setStatus("ACTIVE"); + handlingUnit.setStatusDb("ACTIVE"); + handlingUnit.setFreezeFlag("N"); + handlingUnit.setReserveFlag("N"); + handlingUnit.setMergedFlag("N"); + handlingUnit.setInStockFlag("N"); + handlingUnit.setCreatedDate(new Date()); + handlingUnit.setCreatedBy("SYSTEM"); + handlingUnit.setSourceType("IFS_INIT"); + handlingUnit.setOriginalQty(request.getQty()); // 使用计算后的数量 + handlingUnit.setReceiveDate(newReceiveDate); + handlingUnit.setHeight(request.getHeight()); + + // 根据料号和单位计算长宽 + BigDecimal width = null; + BigDecimal length = null; + + String partNo = request.getPartNo(); + if (partNo != null && partNo.contains("-")) { + // 如果料号带尾缀,比如70001234-0250,那么width就是250 + String[] parts = partNo.split("-"); + String suffix = parts[parts.length - 1]; + try { + int widthVal = Integer.parseInt(suffix); + width = BigDecimal.valueOf(widthVal); + } catch (NumberFormatException e) { + // 默认1000 + } } - outsourcingReturnMapper.updateHandingUnit(handlingUnits); + + // length就是数量乘以1000再除以width + if (width != null && width.compareTo(BigDecimal.ZERO) > 0) { + length = request.getQty().multiply(BigDecimal.valueOf(1000)) + .divide(width, 2, java.math.RoundingMode.HALF_UP); + } + + handlingUnit.setWidth(width); + handlingUnit.setLength(length); + handlingUnit.setManufactureDate(newManufactureDate); + handlingUnit.setExpiredDate(newExpireData); + handlingUnit.setUmId(newUmId); + handlingUnit.setEngChgLevel(newEngChgLevel); // 设置工程变更级别,默认1 + + // 保存HandlingUnit + boolean saveResult = handlingUnitService.save(handlingUnit); + if (!saveResult) { + log.error("严重错误:HandlingUnit保存返回失败!unitId={}", unitId); + handlingUnitIdLogService.logUnitIdGeneration( + unitId, request.getSite(), "IFS_INIT", "", + "", request.getPartNo(), request.getBatchNo(), + request.getQty().doubleValue(), "SYSTEM", + "N", "保存失败-save返回false" + ); + throw new RuntimeException("HandlingUnit保存失败(save返回false): " + unitId); + } + + // 立即验证是否保存成功(防止保存失败但业务继续执行) + HandlingUnit savedUnit = handlingUnitService.getById(unitId); + if (savedUnit == null) { + log.error("严重错误:HandlingUnit保存验证失败!unitId={}", unitId); + // 更新日志为失败 + handlingUnitIdLogService.logUnitIdGeneration( + unitId, request.getSite(), "IFS_INIT", "", + "", request.getPartNo(), request.getBatchNo(), + request.getQty().doubleValue(), "SYSTEM", + "N", "保存失败-验证未通过" + ); + throw new RuntimeException("HandlingUnit保存失败(验证未通过): " + unitId); + } + + // 更新日志为成功 + handlingUnitIdLogService.logUnitIdGeneration( + unitId, request.getSite(), "IFS_INIT", "", + "", request.getPartNo(), request.getBatchNo(), + request.getQty().doubleValue(), "SYSTEM", + "Y", "保存成功" + ); + + return unitId; } } diff --git a/src/main/resources/mapper/outsourcing/OutsourcingReturnMapper.xml b/src/main/resources/mapper/outsourcing/OutsourcingReturnMapper.xml index 444810f..a0d3ed0 100644 --- a/src/main/resources/mapper/outsourcing/OutsourcingReturnMapper.xml +++ b/src/main/resources/mapper/outsourcing/OutsourcingReturnMapper.xml @@ -59,6 +59,24 @@ from handling_unit a where a.site=#{site} and a.unit_id=#{scannedLabel} and (a.in_stock_flag='N' or a.in_stock_flag='X') and a.part_no = #{componentPartNo} + + + @@ -70,4 +88,47 @@ WHERE unit_id = #{hu.unitId} + + + UPDATE handling_unit WITH (ROWLOCK) + SET + reserve_flag = 'N', + reserve_order_ref1 = null, + reserve_order_ref2 = null, + reserve_order_ref3 = null, + location_id = CASE unit_id + + WHEN #{hu.unitId} THEN #{hu.locationId} + + END, + warehouse_id = CASE unit_id + + WHEN #{hu.unitId} THEN #{hu.warehouseId} + + END, + qty = CASE unit_id + + WHEN #{hu.unitId} THEN #{hu.qty} + + END, + height = CASE unit_id + + WHEN #{hu.unitId} THEN #{hu.height} + + END, + modified_date = GETDATE() + WHERE unit_id IN + + #{hu.unitId} + +