Browse Source

2026-04-13

产品BOM和配方BOM删除的判断调整,参考IFS逻辑
master
fengyuan_yang 2 days ago
parent
commit
6d09244fc6
  1. 5
      src/main/java/com/spring/modules/part/mapper/BomManagementMapper.java
  2. 2
      src/main/java/com/spring/modules/part/mapper/RecipeManagementMapper.java
  3. 38
      src/main/java/com/spring/modules/part/service/impl/BomManagementServiceImpl.java
  4. 38
      src/main/java/com/spring/modules/part/service/impl/RecipeManagementServiceImpl.java
  5. 16
      src/main/resources/mapper/part/BomManagementMapper.xml
  6. 19
      src/main/resources/mapper/part/RecipeManagementMapper.xml

5
src/main/java/com/spring/modules/part/mapper/BomManagementMapper.java

@ -128,6 +128,11 @@ public interface BomManagementMapper extends BaseMapper<BomHeaderEntity> {
List<BomDetailVo> queryOfficialBomDetail(BomHeaderEntity headData);
/**
* 正式替代且状态非拟定Tentative的明细存在则不允许整单删除 BOM
*/
List<BomDetailVo> queryOfficialNonTentativeBomDetail(BomHeaderEntity headData);
List<BomComponentVo> selectBomComponentByPartNo(@Param("site") String site, @Param("partNo") String partNo);
List<BomDetailVo> selectBomDetailByPartNo(@Param("site") String site, @Param("partNo") String partNo);

2
src/main/java/com/spring/modules/part/mapper/RecipeManagementMapper.java

@ -128,6 +128,8 @@ public interface RecipeManagementMapper extends BaseMapper<RecipeHeaderEntity> {
List<RecipeDetailVo> queryOfficialRecipeDetail(RecipeHeaderEntity headData);
List<RecipeDetailVo> queryOfficialNonTentativeRecipeDetail(RecipeHeaderEntity headData);
List<RecipeComponentVo> selectRecipeComponentByPartNo(@Param("site") String site, @Param("partNo") String partNo);
List<RecipeDetailVo> selectRecipeDetailByPartNo(@Param("site") String site, @Param("partNo") String partNo);

38
src/main/java/com/spring/modules/part/service/impl/BomManagementServiceImpl.java

@ -26,6 +26,7 @@ import com.spring.modules.sift.utils.QueryCriteriaConstructorDefault;
import com.spring.modules.sift.vo.QuerySavedVo;
import com.spring.modules.sys.dao.SysUserDao;
import com.spring.modules.sys.entity.SysUserEntity;
import org.apache.shiro.SecurityUtils;
import ifs.fnd.ap.Server;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@ -182,21 +183,34 @@ public class BomManagementServiceImpl extends ServiceImpl<BomManagementMapper, B
@Transactional
public void bomManagementDelete(BomHeaderEntity data) {
for (BomHeaderEntity headData : data.getInformationList()) {
// 判断该 BOM 是否有正式替代
List<BomDetailVo> officialAlternativeList = bomManagementMapper.queryOfficialBomDetail(headData);
if (!officialAlternativeList.isEmpty()) {
throw new RuntimeException("物料编码 [" + headData.getPartNo() + "] 制造类型 [" + headData.getBomType() + "] BOM版本号 [" + headData.getEngChgLevel() + "] 的BOM存在正式替代,不能被删除!");
// 存在正式替代且状态非拟定则不允许删除正式拟定替代非正式替代子物料等不再拦截
List<BomDetailVo> officialNonTentativeList = bomManagementMapper.queryOfficialNonTentativeBomDetail(headData);
if (!officialNonTentativeList.isEmpty()) {
throw new RuntimeException("物料编码 [" + headData.getPartNo() + "] 制造类型 [" + headData.getBomType() + "] BOM版本号 [" + headData.getEngChgLevel() + "] 的BOM存在正式且状态非Tentative的替代,不能被删除!");
}
// 判断该 bom 是否有 Buildable Obsolete 状态的替代
List<BomDetailVo> AlternativeList = bomManagementMapper.queryAlternativeStatus(headData);
if (!AlternativeList.isEmpty()) {
throw new RuntimeException("物料编码 [" + headData.getPartNo() + "] 制造类型 [" + headData.getBomType() + "] BOM版本号 [" + headData.getEngChgLevel() + "] 的BOM存在状态为 Buildable、Obsolete 的替代,不能被删除!");
BomHeaderEntity bomHeader = bomManagementMapper.selectOne(new QueryWrapper<BomHeaderEntity>().eq("site", headData.getSite()).eq("part_no", headData.getPartNo()).eq("eng_chg_level", headData.getEngChgLevel()).eq("bom_type", headData.getBomType()));
if (bomHeader == null) {
throw new RuntimeException("BOM不存在!");
}
if (dataUrl && "Y".equals(bomHeader.getOfficialFlag())) {
String ifsUser = ((SysUserEntity) SecurityUtils.getSubject().getPrincipal()).getUsername();
Server srv = getIfsServer(ifsUser);
BomIfsHeader bomIfsHeader = new BomIfsHeader();
bomIfsHeader.setContract(bomHeader.getSite());
bomIfsHeader.setPartNo(bomHeader.getPartNo());
bomIfsHeader.setEngChgLevel(bomHeader.getEngChgLevel().toString());
bomIfsHeader.setBomType(bomHeader.getBomType());
bomIfsHeader.setEffPhaseInDate(DateUtils.format(bomHeader.getEffPhaseInDate()));
bomIfsHeader.setEffPhaseOutDate(bomHeader.getEffPhaseOutDate() == null ? "" : DateUtils.format(bomHeader.getEffPhaseOutDate()));
bomIfsHeader.setNoteText(bomHeader.getNoteText() == null ? "" : bomHeader.getNoteText());
Map<String, String> removeBomHeaderResponse = bomServiceBean.removeBomHeader(srv, bomIfsHeader);
if (!"200".equals(removeBomHeaderResponse.get("resultCode"))) {
throw new RuntimeException("IFS BomHeader删除异常:" + removeBomHeaderResponse.get("resultMsg"));
}
// 判断 BOM 是否存在子料
List<BomComponentVo> componentPartList = bomManagementMapper.queryComponentPart(headData);
if (!componentPartList.isEmpty()) {
throw new RuntimeException("物料编码 [" + headData.getPartNo() + "] 制造类型 [" + headData.getBomType() + "] BOM版本号 [" + headData.getEngChgLevel() + "] 的BOM含有替代物料,请手动删除替代物料后再执行此操作!");
}
// 删除子明细
bomManagementMapper.deleteBomComponentByPartNo(headData);
// 删除明细

38
src/main/java/com/spring/modules/part/service/impl/RecipeManagementServiceImpl.java

@ -29,6 +29,7 @@ import com.spring.modules.sift.utils.QueryCriteriaConstructorDefault;
import com.spring.modules.sift.vo.QuerySavedVo;
import com.spring.modules.sys.dao.SysUserDao;
import com.spring.modules.sys.entity.SysUserEntity;
import org.apache.shiro.SecurityUtils;
import ifs.fnd.ap.Server;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
@ -209,21 +210,34 @@ public class RecipeManagementServiceImpl extends ServiceImpl<RecipeManagementMap
@Transactional
public void recipeManagementDelete(RecipeHeaderEntity data) {
for (RecipeHeaderEntity headData : data.getInformationList()) {
// 判断该 Recipe 是否有正式替代
List<RecipeDetailVo> officialAlternativeList = recipeManagementMapper.queryOfficialRecipeDetail(headData);
if (!officialAlternativeList.isEmpty()) {
throw new RuntimeException("物料编码 [" + headData.getPartNo() + "] 制造类型 [" + headData.getBomType() + "] Recipe版本号 [" + headData.getEngChgLevel() + "] 的Recipe存在正式替代,不能被删除!");
// 存在正式替代且状态非拟定则不允许删除正式拟定替代非正式替代子物料等不再拦截
List<RecipeDetailVo> officialNonTentativeList = recipeManagementMapper.queryOfficialNonTentativeRecipeDetail(headData);
if (!officialNonTentativeList.isEmpty()) {
throw new RuntimeException("物料编码 [" + headData.getPartNo() + "] 制造类型 [" + headData.getBomType() + "] Recipe版本号 [" + headData.getEngChgLevel() + "] 的Recipe存在正式且状态非Tentative的替代,不能被删除!");
}
// 判断该 recipe 是否有 Buildable Obsolete 状态的替代
List<RecipeDetailVo> AlternativeList = recipeManagementMapper.queryAlternativeStatus(headData);
if (!AlternativeList.isEmpty()) {
throw new RuntimeException("物料编码 [" + headData.getPartNo() + "] 制造类型 [" + headData.getBomType() + "] Recipe版本号 [" + headData.getEngChgLevel() + "] 的Recipe存在状态为 Buildable、Obsolete 的替代,不能被删除!");
RecipeHeaderEntity recipeHeader = recipeManagementMapper.selectOne(new QueryWrapper<RecipeHeaderEntity>().eq("site", headData.getSite()).eq("part_no", headData.getPartNo()).eq("eng_chg_level", headData.getEngChgLevel()).eq("bom_type", headData.getBomType()));
if (recipeHeader == null) {
throw new RuntimeException("Recipe不存在!");
}
if (dataUrl && "Y".equals(recipeHeader.getOfficialFlag())) {
String ifsUser = ((SysUserEntity) SecurityUtils.getSubject().getPrincipal()).getUsername();
Server srv = getIfsServer(ifsUser);
RecipeIfsHeader recipeIfsHeader = new RecipeIfsHeader();
recipeIfsHeader.setContract(recipeHeader.getSite());
recipeIfsHeader.setPartNo(recipeHeader.getPartNo());
recipeIfsHeader.setEngChgLevel(recipeHeader.getEngChgLevel().toString());
recipeIfsHeader.setBomType(recipeHeader.getBomType());
recipeIfsHeader.setEffPhaseInDate(DateUtils.format(recipeHeader.getEffPhaseInDate()));
recipeIfsHeader.setEffPhaseOutDate(recipeHeader.getEffPhaseOutDate() == null ? "" : DateUtils.format(recipeHeader.getEffPhaseOutDate()));
recipeIfsHeader.setNoteText(recipeHeader.getNoteText() == null ? "" : recipeHeader.getNoteText());
Map<String, String> removeRecipeHeaderResponse = recipeServiceBean.removeRecipeHeader(srv, recipeIfsHeader);
if (!"200".equals(removeRecipeHeaderResponse.get("resultCode"))) {
throw new RuntimeException("IFS RecipeHeader删除异常:" + removeRecipeHeaderResponse.get("resultMsg"));
}
// 判断 Recipe 是否存在子料
List<RecipeComponentVo> componentPartList = recipeManagementMapper.queryComponentPart(headData);
if (!componentPartList.isEmpty()) {
throw new RuntimeException("物料编码 [" + headData.getPartNo() + "] 制造类型 [" + headData.getBomType() + "] Recipe版本号 [" + headData.getEngChgLevel() + "] 的Recipe含有替代物料,请手动删除替代物料后再执行此操作!");
}
// 删除子明细
recipeManagementMapper.deleteRecipeComponentByPartNo(headData);
// 删除明细

16
src/main/resources/mapper/part/BomManagementMapper.xml

@ -625,6 +625,22 @@
WHERE site = #{site} and part_no = #{partNo} and eng_chg_level = #{engChgLevel} and bom_type = #{bomType} and official_flag = 'Y'
</select>
<!-- 正式替代且状态非拟定:整单删除前校验用 -->
<select id="queryOfficialNonTentativeBomDetail" parameterType="BomHeaderEntity" resultType="com.spring.modules.part.vo.BomDetailVo">
SELECT
site,
part_no,
eng_chg_level,
bom_type,
alternative_no,
status,
official_flag
FROM plm_bom_detail
WHERE site = #{site} and part_no = #{partNo} and eng_chg_level = #{engChgLevel} and bom_type = #{bomType}
and official_flag = 'Y'
and (status IS NULL OR status &lt;&gt; 'Tentative')
</select>
<!-- 判断 BOM 是否存在子料 -->
<select id="queryComponentPart" parameterType="BomHeaderEntity" resultType="com.spring.modules.part.vo.BomComponentVo">
SELECT

19
src/main/resources/mapper/part/RecipeManagementMapper.xml

@ -685,6 +685,25 @@
WHERE site = #{site} and part_no = #{partNo} and eng_chg_level = #{engChgLevel} and bom_type = #{bomType} and official_flag = 'Y'
</select>
<!-- 正式替代且状态非拟定:整单删除前校验用 -->
<select id="queryOfficialNonTentativeRecipeDetail" parameterType="RecipeHeaderEntity" resultType="com.spring.modules.part.vo.RecipeDetailVo">
SELECT
site,
part_no,
eng_chg_level,
bom_type,
alternative_no,
status,
official_flag,
display_weight_uom,
display_volume_uom,
reg_unit
FROM plm_recipe_detail
WHERE site = #{site} and part_no = #{partNo} and eng_chg_level = #{engChgLevel} and bom_type = #{bomType}
and official_flag = 'Y'
and (status IS NULL OR status &lt;&gt; 'Tentative')
</select>
<!-- 判断 Recipe 是否存在子料 -->
<select id="queryComponentPart" parameterType="RecipeHeaderEntity" resultType="com.spring.modules.part.vo.RecipeComponentVo">
SELECT

Loading…
Cancel
Save