Browse Source

委外修改

master
shenzhouyu 3 months ago
parent
commit
dc66f33c26
  1. 4
      src/main/java/com/gaotao/modules/outsourcing/controller/OutsourcingReturnController.java
  2. 13
      src/main/java/com/gaotao/modules/outsourcing/dao/OutsourcingReturnMapper.java
  3. 2
      src/main/java/com/gaotao/modules/outsourcing/entity/dto/MrIssueMaterialDto.java
  4. 2
      src/main/java/com/gaotao/modules/outsourcing/service/OutsourcingReturnService.java
  5. 308
      src/main/java/com/gaotao/modules/outsourcing/service/impl/OutsourcingReturnServiceImpl.java
  6. 61
      src/main/resources/mapper/outsourcing/OutsourcingReturnMapper.xml

4
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<String> ids = outsourcingReturnService.outsourcingReturnUnissueConfirm(dto);
return R.ok().put("unitIds", ids);
} catch (Exception e) {
return R.error(e.getMessage());
}

13
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<HandlingUnit> list);
List<Location> getAllLocation(@Param("site")String site);
Location getLocation(@Param("locationId")String locationId, @Param("site")String site);
HandlingUnit getOneHandlingUnit(@Param("request")CreateHuRequestReturnIssueDto request);
List<HandlingUnit> selectByUnitIds(Set<String> unitIds);
int updateNewHandingUnit(List<HandlingUnit> handlingUnits);
}

2
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;
}

2
src/main/java/com/gaotao/modules/outsourcing/service/OutsourcingReturnService.java

@ -37,7 +37,7 @@ public interface OutsourcingReturnService {
/**
* 确认委外退料
*/
void outsourcingReturnUnissueConfirm(OutsourcingReturnDto dto) throws Exception;
List<String> outsourcingReturnUnissueConfirm(OutsourcingReturnDto dto) throws Exception;
}

308
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<PurchaseOrderLineVo> 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<String> outsourcingReturnUnissueConfirm(OutsourcingReturnDto dto) throws Exception {
if (dto.getSelectedMaterials() == null || dto.getSelectedMaterials().isEmpty()) {
throw new Exception("没有选择要退料的物料");
}
validateLocal(dto.getSelectedMaterials(),dto.getSite());
List<MrIssueMaterialDto> 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<TransCommonSubDto> 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<Location> allLocation = outsourcingReturnMapper.getAllLocation(dto.getSite());
Map<String, String> 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<TransDetail> out = transHeaderService.genTransAndChangeInventoryStock(transCommonRequestDto, "IN");
//前端打印新标签并跟新HandlingUnit的库位和长度
List<HandlingUnit> handlingUnits = new ArrayList<>();
List<String> unitIdPrints = new ArrayList<>();
Set<String> unitIds = dto.getSelectedMaterials().stream()
.map(MrIssueMaterialDto::getLabelCode)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
if (unitIds.isEmpty()) {
throw new IllegalArgumentException("列表中标签号均为空,无法查询数据库");
}
List<HandlingUnit> huList = outsourcingReturnMapper.selectByUnitIds(unitIds);
Map<String, HandlingUnit> 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<HandlingUnit> 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<MrIssueMaterialDto> selectedMaterials, String site) throws Exception{
// 校验库位
Set<String> unitIds = selectedMaterials.stream()
.map(MrIssueMaterialDto::getLocationId)
.collect(Collectors.toSet());
if (CollectionUtils.isEmpty(unitIds)) {
throw new IllegalArgumentException("存在库位为输入");
}
List<Location> allLocation = outsourcingReturnMapper.getAllLocation(site);
Set<String> existingLocationIds = allLocation.stream()
.map(Location::getLocationId)
.filter(locationId -> locationId != null && !locationId.trim().isEmpty()) // 过滤无效值
.map(String::trim)
.collect(Collectors.toSet());
// 3. 筛选出unitIds中不存在于existingLocationIds的元素
Set<String> 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<AnInventoryPartInStockVo> 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;
}
}

61
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}
</select>
<select id="getAllLocation" resultType="com.gaotao.modules.warehouse.entity.Location">
select LocationID,Site,LocationName,WareHouseID,Active,locationGroupId,locationType
from location
where Site = #{site}
</select>
<select id="getLocation" resultType="com.gaotao.modules.warehouse.entity.Location">
select top 1 LocationID,Site,LocationName,WareHouseID,Active,locationGroupId,locationType
from location
where LocationID = #{locationId} and Site = #{site}
</select>
<select id="getOneHandlingUnit" resultType="com.gaotao.modules.handlingunit.entity.HandlingUnit">
select top 1 c.*
from
trans_header a
join trans_detail_sub b on a.trans_no = b.trans_no and a.site = b.site
left join handling_unit c on b.sub_no = c.unit_id and b.site = c.site
where b.part_no = #{request.partNo} and b.batch_no = #{request.batchNo} and a.order_ref1 = #{request.orderNo} and a.site = #{request.site} and c.unit_id is not null
</select>
<!-- 优化:添加 WITH (ROWLOCK) 避免锁升级导致死锁 - rqrq -->
<update id="updateHandingUnit" parameterType="java.util.List">
<foreach collection="list" item="hu" separator=";">
@ -70,4 +88,47 @@
WHERE unit_id = #{hu.unitId}
</foreach>
</update>
<select id="selectByUnitIds" resultType="com.gaotao.modules.handlingunit.entity.HandlingUnit">
SELECT
unit_id,
qty
FROM handling_unit
WHERE unit_id IN
<foreach collection="unitIds" item="unitId" open="(" separator="," close=")">
#{unitId}
</foreach>
</select>
<update id="updateNewHandingUnit" parameterType="java.util.List">
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
<foreach collection="list" item="hu" separator="">
WHEN #{hu.unitId} THEN #{hu.locationId}
</foreach>
END,
warehouse_id = CASE unit_id
<foreach collection="list" item="hu" separator="">
WHEN #{hu.unitId} THEN #{hu.warehouseId}
</foreach>
END,
qty = CASE unit_id
<foreach collection="list" item="hu" separator="">
WHEN #{hu.unitId} THEN #{hu.qty}
</foreach>
END,
height = CASE unit_id
<foreach collection="list" item="hu" separator="">
WHEN #{hu.unitId} THEN #{hu.height}
</foreach>
END,
modified_date = GETDATE()
WHERE unit_id IN
<foreach collection="list" item="hu" open="(" separator="," close=")">
#{hu.unitId}
</foreach>
</update>
</mapper>
Loading…
Cancel
Save