From 4015750c8dd6d42bb2bb1bb39dcc29a384faa733 Mon Sep 17 00:00:00 2001 From: libowen Date: Fri, 9 Jan 2026 15:46:20 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=20'TML=E7=89=A9=E6=96=99=E4=B8=8EBOM=E7=9A=84=E6=80=BB?= =?UTF-8?q?=E8=A7=A6=E5=8F=91=E5=99=A8'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TMLMaterialBOMChange_mxJPO.java | 148 ++++++++++++++++++ TML物料与BOM的总触发器/代码说明.docx | Bin 0 -> 14217 bytes 2 files changed, 148 insertions(+) create mode 100644 TML物料与BOM的总触发器/TMLMaterialBOMChange_mxJPO.java create mode 100644 TML物料与BOM的总触发器/代码说明.docx 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 0000000000000000000000000000000000000000..8e0cc8e4e88a42ed570c38f0fd37095aeedd5ce1 GIT binary patch literal 14217 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 literal 0 HcmV?d00001