diff --git a/TML物料与BOM的总触发器/TMLMaterialBOMChange_mxJPO.java b/TML物料与BOM的总触发器/TMLMaterialBOMChange_mxJPO.java new file mode 100644 index 0000000..1fbc730 --- /dev/null +++ b/TML物料与BOM的总触发器/TMLMaterialBOMChange_mxJPO.java @@ -0,0 +1,148 @@ +import com.matrixone.apps.domain.util.FrameworkException; +import com.matrixone.apps.domain.util.MqlUtil; +import matrix.db.Context; + +import java.util.Set; +import java.util.logging.Logger; + +public class TMLMaterialBOMChange_mxJPO { + + private static final Logger LOGGER = Logger.getLogger(TMLMaterialBOMChange_mxJPO.class.getName()); + + //todo + public String updatePartStateInfo(Context context, String[] args) throws FrameworkException { + String partCode = args[0]; + String partState = args[1]; + LOGGER.info("partCode: " + partCode); + LOGGER.info("partState: " + partState); + +// String getPartId = "temp query bus * * * where 'attribute[].value ==" + partCode + "' select id dump |"; + String getPartId = "temp query bus * " + partCode + " * select id dump |"; + String partIdInfo = MqlUtil.mqlCommand(context, getPartId); + String partId = partIdInfo.split("\\|")[3]; + + String updatePartStateInfo = "modify bus " + partId + " current" + partState + ";"; + LOGGER.info("updatePartStateInfo: " + updatePartStateInfo); + MqlUtil.mqlCommand(context, updatePartStateInfo); + + return "modify Success"; + } + + public void connectBomController(Context context, String[] args) throws FrameworkException { + String componentId = args[0]; + String partId = args[1]; + LOGGER.info("Processing BOM connection: componentId=" + componentId + ", partId=" + partId); + + // 查询属性 + PartAttributes partAttrs = fetchPartAttributes(context, partId); + String componentMaterialScene = fetchComponentMaterialScene(context, componentId); + + // 校验物料场景 + validateMaterialSceneConsistency(componentMaterialScene, partAttrs.materialScene); + + // 校验采购件状态 + validatePurchasedPartMaturity(partId, partAttrs.manufactureMethod, partAttrs.maturityState); + + // 更新引用计数(如需要) + if ("true".equals(partAttrs.isConnectionBOM)) { + incrementNumberOfCitations(context, partId, partAttrs.numberOfCitations); + } + } + + // --- 辅助方法 --- + + private PartAttributes fetchPartAttributes(Context context, String partId) throws FrameworkException { + String selectClause = "attribute[MaterialScene].value " + + "attribute[ManufactureMethod].value " + + "attribute[NumberOfCitations].value " + + "attribute[IsConnectionBOM].value " + + "current"; + + String mql = "print bus " + partId + " select " + selectClause + " dump |"; + String result = MqlUtil.mqlCommand(context, mql).trim(); + + String[] fields = result.split("\\|", -1); // -1 保留尾部空串 + if (fields.length < 8) { + throw new IllegalStateException("Unexpected MQL output format for part: " + partId); + } + + return new PartAttributes( + fields[3], // MaterialScened + fields[4], // ManufactureMethod + fields[5], // NumberOfCitations + fields[6], // IsConnectionBOM + fields[7] // current (maturity state) + ); + } + + private String fetchComponentMaterialScene(Context context, String componentId) throws FrameworkException { + String mql = "print bus " + componentId + " select attribute[MaterialScene].value dump |"; + String result = MqlUtil.mqlCommand(context, mql).trim(); + String[] parts = result.split("\\|", -1); + if (parts.length < 4) { + throw new IllegalStateException("Unexpected MQL output for component: " + componentId); + } + return parts[3]; + } + + private void validateMaterialSceneConsistency(String compScene, String partScene) { + //todo + Set ALLOWED_SCENES = Set.of("A", "B"); + + boolean isMaterialSceneValueForComponent = ALLOWED_SCENES.contains(compScene); + boolean isMaterialSceneValueForPart = ALLOWED_SCENES.contains(partScene); + + if(isMaterialSceneValueForComponent && !isMaterialSceneValueForPart) { + throw new RuntimeException("零部件对应的物料场景不符"); + } + + if(isMaterialSceneValueForComponent && isMaterialSceneValueForPart && !compScene.equals(partScene)) { + throw new RuntimeException("零部件对应的物料场景不符"); + } + } + + + private void validatePurchasedPartMaturity(String partId, String method, String state) { + if ("PurchasedPart".equals(method) && !"RELEASED".equals(state)) { + String msg = "Purchased part [" + partId + "] must have maturity status 'RELEASED', but got: " + state; + throw new BomValidationException(msg); + } + } + + public static class BomValidationException extends RuntimeException { + public BomValidationException(String message) { + super(message); + } + } + + private void incrementNumberOfCitations(Context context, String partId, String currentCountStr) { + try { + int current = Integer.parseInt(currentCountStr.trim()); + int updated = current + 1; + + String mql = "modify bus " + partId + " attribute[NumberOfCitations] " + updated + " ;"; + MqlUtil.mqlCommand(context, mql); + + LOGGER.info("Updated NumberOfCitations for part " + partId + ": " + current + " -> " + updated); + } catch (FrameworkException e) { + throw new IllegalStateException("Invalid NumberOfCitations value: " + currentCountStr, e); + } + } + + private static class PartAttributes { + final String materialScene; + final String manufactureMethod; + final String numberOfCitations; + final String isConnectionBOM; + final String maturityState; // 'current' field + + PartAttributes(String materialScene, String manufactureMethod, + String numberOfCitations, String isConnectionBOM, String maturityState) { + this.materialScene = materialScene; + this.manufactureMethod = manufactureMethod; + this.numberOfCitations = numberOfCitations; + this.isConnectionBOM = isConnectionBOM; + this.maturityState = maturityState; + } + } +} diff --git a/TML物料与BOM的总触发器/代码说明.docx b/TML物料与BOM的总触发器/代码说明.docx new file mode 100644 index 0000000..8e0cc8e --- /dev/null +++ b/TML物料与BOM的总触发器/代码说明.docx @@ -0,0 +1,7 @@ +1. 物料场景,当一个物料的属性值(物料场景)为:研发物料和大仓物料的时候,插入到其他部件的时候,部件的属性值也要是这个; +2. 当属性字段,制造方式:外购时,成熟度状态不为已发布的时候 不能挂部件; +3. 是否入BOM 下拉值 枚举单选:是、否(默认是) 值为否的料,防错处理,不允许搭入BOM +4. 引用次数 被引用到多少个已发布的BOM内(系统统计) +5. 文档上传根据文档名称自动上传到物料中 ==> 只有.dwg才这样做 + +改物料与BOM的对应卡控点的触发器