|
|
|
@ -17,10 +17,14 @@ import org.apache.shiro.SecurityUtils; |
|
|
|
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.util.ArrayList; |
|
|
|
import java.util.HashSet; |
|
|
|
import java.util.LinkedHashSet; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Set; |
|
|
|
|
|
|
|
@Service |
|
|
|
public class OutboundNotificationServiceImpl implements OutboundNotificationService { |
|
|
|
@ -150,6 +154,7 @@ public class OutboundNotificationServiceImpl implements OutboundNotificationServ |
|
|
|
@Override |
|
|
|
@Transactional |
|
|
|
public void saveOutboundDetail(OutboundNotificationDetailVo data) { |
|
|
|
validateOutboundDetailNotDuplicate(data); |
|
|
|
List<OutboundNotificationDetailVo> inbounds = new ArrayList<>(); |
|
|
|
for (PartInformationVo part : data.getPartList()) { |
|
|
|
OutboundNotificationDetailVo detailVo = getInboundNotificationDetailVo(data, part); |
|
|
|
@ -165,6 +170,115 @@ public class OutboundNotificationServiceImpl implements OutboundNotificationServ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 保存出库明细前防重复:按 site + 采购订单 + 行号校验。 |
|
|
|
*/ |
|
|
|
private void validateOutboundDetailNotDuplicate(OutboundNotificationDetailVo data) { |
|
|
|
if (data == null || !StringUtils.hasText(data.getOrderNo())) { |
|
|
|
throw new RuntimeException("出库单号不能为空"); |
|
|
|
} |
|
|
|
List<PartInformationVo> partList = data.getPartList(); |
|
|
|
if (partList == null || partList.isEmpty()) { |
|
|
|
throw new RuntimeException("请选择物料!"); |
|
|
|
} |
|
|
|
|
|
|
|
PartInformationVo firstPart = partList.get(0); |
|
|
|
String site = StringUtils.hasText(data.getSite()) ? data.getSite().trim() : (firstPart == null ? null : trimToEmpty(firstPart.getSite())); |
|
|
|
String buNo = StringUtils.hasText(data.getBuNo()) ? data.getBuNo() : (firstPart == null ? null : firstPart.getBuNo()); |
|
|
|
if (!StringUtils.hasText(site) || !StringUtils.hasText(buNo)) { |
|
|
|
throw new RuntimeException("工厂或事业部不能为空"); |
|
|
|
} |
|
|
|
data.setSite(site); |
|
|
|
data.setBuNo(buNo); |
|
|
|
|
|
|
|
LinkedHashSet<String> requestKeys = new LinkedHashSet<>(); |
|
|
|
List<String> duplicateDisplays = new ArrayList<>(); |
|
|
|
for (PartInformationVo part : partList) { |
|
|
|
if (part == null) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
String key = buildOutboundDuplicateKey(site, part); |
|
|
|
if (!StringUtils.hasText(key)) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (!requestKeys.add(key)) { |
|
|
|
String display = buildOutboundDuplicateDisplay(part); |
|
|
|
if (!duplicateDisplays.contains(display)) { |
|
|
|
duplicateDisplays.add(display); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (!duplicateDisplays.isEmpty()) { |
|
|
|
throw new RuntimeException("已选物料存在重复采购订单+行号:" + String.join("、", duplicateDisplays)); |
|
|
|
} |
|
|
|
|
|
|
|
OutboundNotificationDetailVo query = new OutboundNotificationDetailVo(); |
|
|
|
query.setSite(site); |
|
|
|
query.setBuNo(buNo); |
|
|
|
query.setOrderNo(data.getOrderNo()); |
|
|
|
List<OutboundNotificationDetailVo> existingList = detailMapper.getOutboundDetail(query); |
|
|
|
if (existingList == null || existingList.isEmpty()) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
Set<String> existingKeys = new HashSet<>(); |
|
|
|
for (OutboundNotificationDetailVo row : existingList) { |
|
|
|
if (row == null) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
String key = buildOutboundDuplicateKey(site, row.getRelatedOrderNo(), row.getRelatedOrderLineNo(), row.getPartNo()); |
|
|
|
if (StringUtils.hasText(key)) { |
|
|
|
existingKeys.add(key); |
|
|
|
} |
|
|
|
} |
|
|
|
List<String> conflictDisplays = new ArrayList<>(); |
|
|
|
for (PartInformationVo part : partList) { |
|
|
|
if (part == null) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
String key = buildOutboundDuplicateKey(site, part); |
|
|
|
if (StringUtils.hasText(key) && existingKeys.contains(key)) { |
|
|
|
String display = buildOutboundDuplicateDisplay(part); |
|
|
|
if (!conflictDisplays.contains(display)) { |
|
|
|
conflictDisplays.add(display); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (!conflictDisplays.isEmpty()) { |
|
|
|
throw new RuntimeException("以下采购订单+行号已存在于出库明细中,请勿重复添加:" + String.join("、", conflictDisplays)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private String buildOutboundDuplicateKey(String site, PartInformationVo part) { |
|
|
|
if (part == null) { |
|
|
|
return ""; |
|
|
|
} |
|
|
|
String partSite = StringUtils.hasText(part.getSite()) ? part.getSite().trim() : site; |
|
|
|
return buildOutboundDuplicateKey(partSite, part.getRelatedOrderNo(), part.getRelatedOrderLineNo(), part.getPartNo()); |
|
|
|
} |
|
|
|
|
|
|
|
private String buildOutboundDuplicateKey(String site, String relatedOrderNo, String relatedOrderLineNo, String partNo) { |
|
|
|
String orderNo = trimToEmpty(relatedOrderNo); |
|
|
|
String lineNo = trimToEmpty(relatedOrderLineNo); |
|
|
|
if (StringUtils.hasText(orderNo) && StringUtils.hasText(lineNo)) { |
|
|
|
return trimToEmpty(site) + "|" + orderNo + "|" + lineNo; |
|
|
|
} |
|
|
|
return StringUtils.hasText(partNo) ? trimToEmpty(partNo) : ""; |
|
|
|
} |
|
|
|
|
|
|
|
private String buildOutboundDuplicateDisplay(PartInformationVo part) { |
|
|
|
String orderNo = trimToEmpty(part.getRelatedOrderNo()); |
|
|
|
String lineNo = trimToEmpty(part.getRelatedOrderLineNo()); |
|
|
|
if (StringUtils.hasText(orderNo) && StringUtils.hasText(lineNo)) { |
|
|
|
return orderNo + " / " + lineNo; |
|
|
|
} |
|
|
|
return trimToEmpty(part.getPartNo()); |
|
|
|
} |
|
|
|
|
|
|
|
private String trimToEmpty(String value) { |
|
|
|
return value == null ? "" : value.trim(); |
|
|
|
} |
|
|
|
|
|
|
|
private static OutboundNotificationDetailVo getInboundNotificationDetailVo(OutboundNotificationDetailVo data, PartInformationVo part) { |
|
|
|
OutboundNotificationDetailVo detailVo = new OutboundNotificationDetailVo(); |
|
|
|
detailVo.setSite(part.getSite()); |
|
|
|
|