配合示方生成混炼示方优化

This commit is contained in:
2026-07-30 17:40:31 +08:00
parent 5c27bacd11
commit dea9b7a58c
15 changed files with 541 additions and 107 deletions

View File

@@ -1361,3 +1361,32 @@ jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
-- author:jiangxh---date:20260730--for: <20><><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD><CFA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD><D8A3><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EBBDBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> ---
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/mes/material/controller/MesMaterialController.java
jeecgboot-vue3/src/views/mes/material/MesMaterial.data.ts
-- author:jiangxh---date:20260730--for: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>ɡ<EFBFBD><C9A1><EFBFBD><EFBFBD><EFBFBD>ƴ<EFBFBD><EFBFBD>ţ<EFBFBD><C5A3><EFBFBD>ϸ<EFBFBD><CFB8><EFBFBD>ϲ<EFBFBD>ƴ<EFBFBD><EFBFBD><E6B1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̶<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD> ---
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
-- author:jiangxh---date:20260730--for: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>ɡ<EFBFBD>ͬһ<CDAC><D2BB><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>Σ<EFBFBD><CEA3><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
-- author:jiangxh---date:20260730--for: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD>ͣ<EFBFBD><CDA3>ͬ<EFBFBD><CDAC>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ ---
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixingSpecServiceImpl.java
-- author:jiangxh---date:20260730--for: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>ɡ<EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD>;NP FOR<4F><52>һ<EFBFBD>ι<EFBFBD><CEB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;ȡ<CDBE><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
-- author:jiangxh---date:20260730--for: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>𽺼<EFBFBD><F0BDBABC><EFBFBD><EFBFBD>ϼ<EFBFBD><CFBC><EFBFBD>ϸ<EFBFBD>ۼ<EFBFBD><DBBC>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>λС<CEBB><D0A1> ---
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixingSpecServiceImpl.java
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
-- author:jiangxh---date:20260730--for: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>𽺼<EFBFBD><F0BDBABC><EFBFBD><EFBFBD>ϼ<EFBFBD><CFBC><EFBFBD>ϸ<EFBFBD><CFB8><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>λС<CEBB><D0A1> ---
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixingSpecServiceImpl.java
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
-- author:jiangxh---date:20260730--for: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>PS<50><53><EFBFBD><EFBFBD><EFBFBD>ɷ<EFBFBD><C9B7><EFBFBD><EFBFBD><EFBFBD>׼<EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>(recognition_pass) ---
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslMixerPsCompileService.java
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixerPsCompileServiceImpl.java
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixingSpecServiceImpl.java
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslMixingSpecService.java
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/approval/integration/engine/executor/RegistryStageSyncExecutor.java
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/approval/integration/engine/executor/RegistryStageRevertExecutor.java

View File

@@ -9,6 +9,7 @@ import org.jeecg.modules.xslmes.approval.integration.entity.MesXslBizDocRegistry
import org.jeecg.modules.xslmes.approval.integration.entity.MesXslIntegrationAction;
import org.jeecg.modules.xslmes.approval.integration.service.IApprovalTraceSyncService;
import org.jeecg.modules.xslmes.approval.integration.service.IMesXslBizDocRegistryService;
import org.jeecg.modules.xslmes.service.IMesXslMixerPsCompileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@@ -26,6 +27,12 @@ public class RegistryStageRevertExecutor implements IIntegrationActionExecutor {
private IApprovalTraceSyncService approvalTraceSyncService;
@Autowired
private JdbcTemplate jdbcTemplate;
//update-begin---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
@Autowired
private IMesXslMixerPsCompileService mesXslMixerPsCompileService;
private static final String BIZ_TABLE_MIXER_PS = "mes_xsl_mixer_ps_compile";
//update-end---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
@Override
public String supportActionType() {
return "REGISTRY_STAGE_REVERT";
@@ -57,6 +64,16 @@ public class RegistryStageRevertExecutor implements IIntegrationActionExecutor {
RegistryStageFieldHelper.assertIdentifier(statusField);
RegistryStageFieldHelper.assertIdentifier(bizTable);
//update-begin---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
String previousStatus = null;
if (BIZ_TABLE_MIXER_PS.equals(bizTable)) {
Object current = jdbcTemplate.queryForObject(
"SELECT `" + statusField + "` FROM `" + bizTable + "` WHERE id = ?",
Object.class, bizId);
previousStatus = current == null ? null : String.valueOf(current).trim();
}
//update-end---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
//update-begin---author:GHT ---date:20260609 for【审批注册中心】回退只重置业务表状态操作人/时间由痕迹表承载-----------
int affected = jdbcTemplate.update(
"UPDATE `" + bizTable + "` SET `" + statusField + "`=? WHERE id=?",
@@ -67,6 +84,11 @@ public class RegistryStageRevertExecutor implements IIntegrationActionExecutor {
}
approvalTraceSyncService.revertToStage(bizTable, bizId, targetStage);
//update-begin---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
if (BIZ_TABLE_MIXER_PS.equals(bizTable)) {
mesXslMixerPsCompileService.cascadeRelatedAfterStageRevert(bizId, previousStatus, targetStage);
}
//update-end---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
log.info("[集成引擎][REGISTRY_STAGE_REVERT] table={} id={} targetStage={}", bizTable, bizId, targetStage);
return "环节回退成功: " + targetStage;
}

View File

@@ -13,6 +13,7 @@ import org.jeecg.modules.xslmes.approval.integration.entity.MesXslIntegrationAct
import org.jeecg.modules.xslmes.approval.integration.entity.MesXslIntegrationPlan;
import org.jeecg.modules.xslmes.approval.integration.service.IApprovalTraceSyncService;
import org.jeecg.modules.xslmes.approval.integration.service.IMesXslBizDocRegistryService;
import org.jeecg.modules.xslmes.service.IMesXslMixerPsCompileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@@ -30,6 +31,12 @@ public class RegistryStageSyncExecutor implements IIntegrationActionExecutor {
private IApprovalTraceSyncService approvalTraceSyncService;
@Autowired
private JdbcTemplate jdbcTemplate;
//update-begin---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
@Autowired
private IMesXslMixerPsCompileService mesXslMixerPsCompileService;
//update-end---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
private static final String BIZ_TABLE_MIXER_PS = "mes_xsl_mixer_ps_compile";
@Override
public String supportActionType() {
@@ -96,6 +103,11 @@ public class RegistryStageSyncExecutor implements IIntegrationActionExecutor {
}
approvalTraceSyncService.syncStage(bizTable, bizId, stage, operator, now);
//update-begin---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
if (BIZ_TABLE_MIXER_PS.equals(bizTable)) {
mesXslMixerPsCompileService.cascadeRelatedAfterStageSync(bizId, statusAfter, operator, now);
}
//update-end---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
log.info("[集成引擎][REGISTRY_STAGE_SYNC] table={} id={} stage={} statusAfter={} operator={}",
bizTable, bizId, stage, statusAfter, operator);
return "环节同步成功: " + ApprovalStageResolver.stageLabel(stage) + " → 状态=" + statusAfter;

View File

@@ -34,4 +34,20 @@ public interface IMesXslMixerPsCompileService extends IService<MesXslMixerPsComp
*/
String withdrawBatch(String ids, String operatorName);
//update-end---author:GHT ---date:2026-05-29 for【QH-MES审批流设计】密炼PS拒绝/撤回逆向回退-----------
//update-begin---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
/**
* 集成方案 REGISTRY_STAGE_SYNC 更新密炼PS状态后联动配合示方/混炼示方(发行编号=PS编码及原材料检验标准。
* 批准(approve)时示方状态写入 recognition_pass承认审批通过-即正式发布)。
*/
void cascadeRelatedAfterStageSync(String psId, String targetStatus, String operatorName, java.util.Date operatorTime);
/**
* 集成方案 REGISTRY_STAGE_REVERT 回退密炼PS状态后联动回退配合示方/混炼示方及原材料检验标准。
*
* @param previousStatus 回退前密炼PS状态
* @param targetStatus 回退后目标状态
*/
void cascadeRelatedAfterStageRevert(String psId, String previousStatus, String targetStatus);
//update-end---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
}

View File

@@ -41,7 +41,8 @@ public interface IMesXslMixingSpecService extends IService<MesXslMixingSpec> {
//update-begin---author:cursor ---date:20260526 for【XSLMES-20260526-A61】混炼示方密炼PS审批联动同步审批人-----------
/**
* 密炼PS校对/审核/批准后按发行编号PS编码同步关联混炼示方审批人
* 密炼PS校对/审核/批准后按发行编号PS编码同步关联混炼示方状态与审批人
* 批准时状态为 recognition_pass承认审批通过-即正式发布)。
*
* @param ps 已更新后的密炼PS编制单
* @param mixerPsTargetStatus 密炼PS目标状态proofread / audit / approve
@@ -50,7 +51,7 @@ public interface IMesXslMixingSpecService extends IService<MesXslMixingSpec> {
//update-begin---author:GHT ---date:2026-05-29 for【QH-MES审批流设计】密炼PS拒绝/撤回联动回退混炼示方-----------
/**
* 密炼PS拒绝/撤回时按发行编号PS编码清空关联混炼示方高于目标状态的审批人痕迹。
* 密炼PS拒绝/撤回时按发行编号PS编码关联混炼示方回退到目标状态,并清空高于目标状态的审批人痕迹。
*
* @param ps 已回退后的密炼PS编制单
* @param mixerPsTargetStatus 密炼PS回退后的目标状态compile / proofread / audit

View File

@@ -565,6 +565,9 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
throw new IllegalArgumentException("请先维护混合段数");
}
String rubberName = resolveRubberName(main);
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】规格拼版本号明细胶料不拼-----------
String formulaCodeSuffix = resolveFormulaCodeSuffix(main);
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】规格拼版本号明细胶料不拼-----------
boolean hasQ = hasStepQ(main.getLineList());
List<MesXslFormulaMixingGeneratePreviewItemVO> items = new ArrayList<>();
int aIndex = 0;
@@ -575,20 +578,23 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
item.setStageIndex(i);
if (isQSegment) {
item.setStepType("Q");
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】B/F匹配编号不拼版本后缀-----------
item.setSpecCode(buildBfRubberSpecCode("F", rubberName));
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】B/F匹配编号不拼版本后缀-----------
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】规格=B/F+胶料名+版本号-----------
item.setSpecCode(appendFormulaCodeSuffix(buildBfRubberSpecCode("F", rubberName), formulaCodeSuffix));
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】规格=B/F+胶料名+版本号-----------
item.setASegmentIndex(null);
} else {
aIndex++;
item.setStepType("A");
item.setASegmentIndex(aIndex);
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】B/F匹配编号不拼版本后缀-----------
item.setSpecCode(buildBfRubberSpecCode("B" + aIndex, rubberName));
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】B/F匹配编号不拼版本后缀-----------
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】规格=B/F+胶料名+版本号-----------
item.setSpecCode(appendFormulaCodeSuffix(buildBfRubberSpecCode("B" + aIndex, rubberName), formulaCodeSuffix));
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】规格=B/F+胶料名+版本号-----------
}
items.add(item);
}
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】同一配合示方仅允许生成一次-----------
assertMixingSpecsNotYetGeneratedByPreview(items);
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】同一配合示方仅允许生成一次-----------
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】列表点生成混炼示方时即匹配胶料列表-----------
// 点击「生成混炼示方」打开预览时即校验拼接示方编号是否已在胶料列表维护
assertRequiredRubberMaterialsExist(toGenerateRowsFromPreviewItems(items), main, main.getLineList());
@@ -630,6 +636,9 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
int created = 0;
int totalStages = normalizeMixingStages(formula.getMixingStages());
Date today = Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant());
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】同一配合示方仅允许生成一次-----------
assertMixingSpecsNotYetGeneratedByRows(request.getRows());
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】同一配合示方仅允许生成一次-----------
//update-begin---author:jiangxh ---date:20260729 for【混炼示方生成】B/F胶料改为胶料列表匹配不存在则提示先维护-----------
Map<String, String> categoryIdCache = new HashMap<>();
assertRequiredRubberMaterialsExist(request.getRows(), formula, lines);
@@ -659,7 +668,9 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
}
MesXslMixingSpec mixing = new MesXslMixingSpec();
mixing.setSpecName(row.getSpecCode());
mixing.setPurpose(formula.getPurpose());
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】母炼用途NP FOR下一段终炼用途取胶料类别-----------
mixing.setPurpose(resolveGeneratedMixingPurpose(row, request.getRows(), formula, categoryNameCache));
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】母炼用途NP FOR下一段终炼用途取胶料类别-----------
mixing.setIssueNumber(formula.getIssueNumber());
mixing.setMachineId(machine.getMachineId());
mixing.setMachineName(machine.getMachineName());
@@ -704,6 +715,70 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
return created;
}
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】母炼/终炼用途拼接规则-----------
/**
* 生成混炼示方用途:
* - 母炼B段NP FOR + 下一段规格(含版本号),如 NP FOR B2XC001SA01
* - 终炼F段胶料类别名称如 注射胶
*/
private String resolveGeneratedMixingPurpose(
MesXslFormulaMixingGenerateRowVO row,
List<MesXslFormulaMixingGenerateRowVO> allRows,
MesXslFormulaSpec formula,
Map<String, String> categoryNameCache) {
if (row == null) {
return "";
}
boolean isFinalStage = "Q".equalsIgnoreCase(resolveMixingMaterialStep(row));
if (isFinalStage) {
return resolveFinalMixingPurpose(formula, categoryNameCache);
}
String nextSpecCode = findNextStageSpecCode(row, allRows);
if (StringUtils.isNotBlank(nextSpecCode)) {
return "NP FOR " + nextSpecCode.trim();
}
// 无下一段时回退为终炼用途规则
return resolveFinalMixingPurpose(formula, categoryNameCache);
}
/** 终炼用途:取所选胶料的类别名(如注射胶);类别为空时回退配合示方用途 */
private String resolveFinalMixingPurpose(MesXslFormulaSpec formula, Map<String, String> categoryNameCache) {
String categoryId = resolveGeneratedRubberCategoryId(formula);
String categoryName = resolveCategoryName(categoryId, categoryNameCache);
if (StringUtils.isNotBlank(categoryName)) {
return categoryName.trim();
}
if (formula != null && StringUtils.isNotBlank(formula.getPurpose())) {
return formula.getPurpose().trim();
}
return "";
}
/** 按混合段序号找下一段规格编号 */
private String findNextStageSpecCode(
MesXslFormulaMixingGenerateRowVO current,
List<MesXslFormulaMixingGenerateRowVO> allRows) {
if (current == null || current.getStageIndex() == null || CollectionUtils.isEmpty(allRows)) {
return null;
}
int currentStage = current.getStageIndex();
MesXslFormulaMixingGenerateRowVO next = null;
for (MesXslFormulaMixingGenerateRowVO row : allRows) {
if (row == null || row.getStageIndex() == null || StringUtils.isBlank(row.getSpecCode())) {
continue;
}
int stage = row.getStageIndex();
if (stage <= currentStage) {
continue;
}
if (next == null || stage < next.getStageIndex()) {
next = row;
}
}
return next != null ? next.getSpecCode().trim() : null;
}
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】母炼/终炼用途拼接规则-----------
//update-begin---author:cursor ---date:20260525 for【XSLMES-20260525-A44】生成混炼示方时按设备有效体积计算填充体积-----------
/** 配合示方整体比重(终炼胶比重)= TOTAL PHR ÷ 全部明细体积合计 */
private BigDecimal resolveCompoundSpecificGravity(MesXslFormulaSpec formula, List<MesXslFormulaSpecLine> lines) {
@@ -804,6 +879,53 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
//update-end---author:cursor ---date:20260525 for【XSLMES-20260525-A44】生成混炼示方时按设备有效体积计算填充体积-----------
//update-begin---author:cursor ---date:20260601 for【XSLMES-20260601-A62】生成混炼示方改为同步B/F段胶至胶料信息-----------
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】同一配合示方仅允许生成一次-----------
/** 预览项:若对应规格混炼示方已存在则禁止再次生成 */
private void assertMixingSpecsNotYetGeneratedByPreview(
List<MesXslFormulaMixingGeneratePreviewItemVO> items) {
if (CollectionUtils.isEmpty(items)) {
return;
}
LinkedHashSet<String> specNames = new LinkedHashSet<>();
for (MesXslFormulaMixingGeneratePreviewItemVO item : items) {
if (item != null && StringUtils.isNotBlank(item.getSpecCode())) {
specNames.add(item.getSpecCode().trim());
}
}
assertMixingSpecNamesNotExist(specNames);
}
/** 确认行:若对应规格混炼示方已存在则禁止再次生成 */
private void assertMixingSpecsNotYetGeneratedByRows(List<MesXslFormulaMixingGenerateRowVO> rows) {
if (CollectionUtils.isEmpty(rows)) {
return;
}
LinkedHashSet<String> specNames = new LinkedHashSet<>();
for (MesXslFormulaMixingGenerateRowVO row : rows) {
if (row != null && StringUtils.isNotBlank(row.getSpecCode())) {
specNames.add(row.getSpecCode().trim());
}
}
assertMixingSpecNamesNotExist(specNames);
}
/** 若已存在同规格混炼示方,则禁止再次生成 */
private void assertMixingSpecNamesNotExist(Collection<String> specNames) {
if (CollectionUtils.isEmpty(specNames)) {
return;
}
long count = mesXslMixingSpecService.count(
new LambdaQueryWrapper<MesXslMixingSpec>()
.in(MesXslMixingSpec::getSpecName, specNames)
.and(w -> w.eq(MesXslMixingSpec::getDelFlag, CommonConstant.DEL_FLAG_0)
.or()
.isNull(MesXslMixingSpec::getDelFlag)));
if (count > 0) {
throw new IllegalArgumentException("该配合示方已生成过混炼示方,请先删除对应混炼示方后再重新生成");
}
}
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】同一配合示方仅允许生成一次-----------
//update-begin---author:jiangxh ---date:20260729 for【混炼示方生成】B/F胶料改为胶料列表匹配不存在则提示先维护-----------
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】预览项转生成行供胶料匹配校验-----------
/** 预览行转为生成行结构,供胶料匹配校验复用 */
@@ -829,7 +951,7 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】预览项转生成行供胶料匹配校验-----------
/**
* 生成前校验:按 B段序号/F + 胶料名 拼出的示方编号,必须已在胶料信息中存在;不再自动新建
* 生成前校验:按 B段序号/F + 胶料名(不含版本号)匹配胶料信息;规格上的 SA01 等不参与匹配
* 在列表点击「生成混炼示方」预览时即调用,确认生成时再次校验。
*/
private void assertRequiredRubberMaterialsExist(
@@ -842,24 +964,27 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
LinkedHashSet<String> requiredCodes = new LinkedHashSet<>();
String rubberName = resolveRubberName(formula);
for (MesXslFormulaMixingGenerateRowVO row : rows) {
if (row == null || StringUtils.isBlank(row.getSpecCode())) {
if (row == null) {
continue;
}
requiredCodes.add(row.getSpecCode().trim());
String stepFilter = resolveMixingMaterialStep(row);
int mixingColumn = resolveMixingColumn(row, formula);
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】胶料匹配用不含版本号的B/F名-----------
if ("Q".equalsIgnoreCase(stepFilter)) {
if (StringUtils.isNotBlank(rubberName)) {
requiredCodes.add(buildBfRubberSpecCode("F", rubberName));
}
int lastBSegment = resolveLastBSegmentIndex(formula, lines);
if (lastBSegment > 0 && StringUtils.isNotBlank(rubberName)) {
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】母胶匹配不拼版本后缀-----------
requiredCodes.add(buildBfRubberSpecCode("B" + lastBSegment, rubberName));
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】母胶匹配不拼版本后缀-----------
}
} else if (mixingColumn > 1 && StringUtils.isNotBlank(rubberName)) {
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】母胶匹配不拼版本后缀-----------
requiredCodes.add(buildBfRubberSpecCode("B" + (mixingColumn - 1), rubberName));
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】母胶匹配不拼版本后缀-----------
} else if (StringUtils.isNotBlank(rubberName)) {
requiredCodes.add(buildBfRubberSpecCode("B" + mixingColumn, rubberName));
if (mixingColumn > 1) {
requiredCodes.add(buildBfRubberSpecCode("B" + (mixingColumn - 1), rubberName));
}
}
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】胶料匹配用不含版本号的B/F名-----------
}
List<String> missing = new ArrayList<>();
for (String code : requiredCodes) {
@@ -1022,9 +1147,8 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
/**
* 配合示方胶料代号/示方编号中,胶料名称之后的后缀原样截取(如 SA01、SB01 等)。
* @deprecated 生成混炼示方匹配胶料已改为仅 B/F+胶料名,不再拼接版本后缀
* 用于混炼示方「规格」拼接;明细胶料匹配不使用此后缀
*/
@Deprecated
private String resolveFormulaCodeSuffix(MesXslFormulaSpec main) {
if (main == null) {
return "";
@@ -1051,10 +1175,7 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
return "";
}
/**
* @deprecated 生成混炼示方匹配胶料已改为仅 B/F+胶料名,请使用 {@link #buildBfRubberSpecCode(String, String)}
*/
@Deprecated
/** 混炼示方规格编号追加版本后缀(如 SA01 */
private String appendFormulaCodeSuffix(String baseSpecCode, String formulaCodeSuffix) {
if (StringUtils.isBlank(baseSpecCode)) {
return baseSpecCode;
@@ -1065,15 +1186,15 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
return baseSpecCode + formulaCodeSuffix;
}
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】B/F匹配编号仅前缀+胶料名-----------
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】明细胶料匹配编号仅前缀+胶料名-----------
/**
* 生成/匹配用示方编号仅「B{n}/F + 胶料名」,不拼接 SA01 等版本号。
* 例:胶料 XC001 三段 → B1XC001、B2XC001、FXC001
* 明细胶料匹配用编号仅「B{n}/F + 胶料名」,不拼接 SA01 等版本号。
* 例:胶料 XC001 → B1XC001、B2XC001、FXC001(规格另拼版本号)
*/
private String buildBfRubberSpecCode(String phasePrefix, String rubberName) {
return StringUtils.defaultString(phasePrefix) + StringUtils.defaultString(rubberName).trim();
}
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】B/F匹配编号仅前缀+胶料名-----------
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】明细胶料匹配编号仅前缀+胶料名-----------
private boolean hasStepQ(List<MesXslFormulaSpecLine> lines) {
if (CollectionUtils.isEmpty(lines)) {
@@ -1263,7 +1384,9 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
ensureMotherRubberMaterialSynced(motherSpecCode, formula, categoryIdCache);
MesXslMixingSpecMaterial material = new MesXslMixingSpecMaterial();
material.setSortNo(sortNo);
material.setUnitWeight(unitWeight);
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
material.setUnitWeight(unitWeight == null ? null : unitWeight.setScale(3, RoundingMode.HALF_UP));
//update-end---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
MesMaterial rubber = findRubberMaterialByCodeOrName(motherSpecCode.trim());
if (rubber != null) {
fillMixingMaterialFromRubberMaterial(material, rubber, categoryNameCache, kindLookup);
@@ -1343,20 +1466,13 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
material.setMaterialMajor(null);
material.setMaterialMinor(categoryName);
material.setMixerMaterialId(rubber.getId());
//update-begin---author:jiangxh ---date:20260729 for【混炼示方生成】母胶行种类按配置解析,未命中则带入胶料兜底种类-----------
String kind = mesXslMixerMaterialKindCfgService.resolveMixingMaterialKind(
kindLookup, rubber.getCategoryId(), null, categoryName);
if (StringUtils.isBlank(kind) && kindLookup != null && StringUtils.isNotBlank(kindLookup.getRubberKindName())) {
kind = kindLookup.getRubberKindName().trim();
}
if (StringUtils.isBlank(kind)) {
kind = "胶料";
}
material.setMaterialKind(kind);
//update-end---author:jiangxh ---date:20260729 for【混炼示方生成】母胶行种类按配置解析未命中则带入胶料兜底种类-----------
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】明细胶料种类固定为「胶料」-----------
// 明细母胶/终胶种类固定「胶料」,不取注射胶、胎面胶等类别名
material.setMaterialKind(resolveRubberMaterialKindName(kindLookup));
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】明细胶料种类固定为「胶料」-----------
}
/** 未查到胶料信息时,按配合示方胶料类别从配置表解析种类 */
/** 未查到胶料信息时,按配合示方胶料类别回填小类展示,种类仍固定为「胶料」 */
private void fillMotherRubberCategoryFallback(
MesXslMixingSpecMaterial material,
MesXslFormulaSpec formula,
@@ -1366,17 +1482,17 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
String categoryName = resolveCategoryName(categoryId, categoryNameCache);
material.setMaterialMajor(null);
material.setMaterialMinor(categoryName);
//update-begin---author:jiangxh ---date:20260729 for【混炼示方生成】母胶兜底种类带入胶料种类-----------
String kind = mesXslMixerMaterialKindCfgService.resolveMixingMaterialKind(
kindLookup, categoryId, null, categoryName);
if (StringUtils.isBlank(kind) && kindLookup != null && StringUtils.isNotBlank(kindLookup.getRubberKindName())) {
kind = kindLookup.getRubberKindName().trim();
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】明细胶料种类固定为「胶料」-----------
material.setMaterialKind(resolveRubberMaterialKindName(kindLookup));
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】明细胶料种类固定为「胶料」-----------
}
/** 明细胶料种类:优先取种类配置中的胶料种类名,默认「胶料」 */
private String resolveRubberMaterialKindName(MesXslMixerMaterialKindLookupVO kindLookup) {
if (kindLookup != null && StringUtils.isNotBlank(kindLookup.getRubberKindName())) {
return kindLookup.getRubberKindName().trim();
}
if (StringUtils.isBlank(kind)) {
kind = "胶料";
}
material.setMaterialKind(kind);
//update-end---author:jiangxh ---date:20260729 for【混炼示方生成】母胶兜底种类带入胶料种类-----------
return "胶料";
}
//update-end---author:cursor ---date:20260601 for【XSLMES-20260601-A62】母胶明细行按胶料信息回填-----------
//update-end---author:cursor ---date:20260525 for【XSLMES-20260525-A54】母炼胶明细行绑定已同步密炼物料主数据-----------
@@ -1462,7 +1578,9 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
material.setMixerMaterialName(line.getMixerMaterialName());
material.setMixerMaterialDesc(
StringUtils.isNotBlank(line.getMaterialDesc()) ? line.getMaterialDesc() : line.getMixerMaterialName());
material.setUnitWeight(unitWeight);
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
material.setUnitWeight(unitWeight == null ? null : unitWeight.setScale(3, RoundingMode.HALF_UP));
//update-end---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
fillMaterialCategory(material, line.getMixerMaterialId(), line, mixerCache, categoryNameCache, kindLookup);
return material;
}

View File

@@ -207,4 +207,44 @@ public class MesXslMixerPsCompileServiceImpl extends ServiceImpl<MesXslMixerPsCo
}
}
//update-end---author:GHT ---date:2026-05-29 for【QH-MES审批流设计】密炼PS拒绝/撤回逆向回退-----------
//update-begin---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
@Override
public void cascadeRelatedAfterStageSync(String psId, String targetStatus, String operatorName, Date operatorTime) {
if (oConvertUtils.isEmpty(psId) || oConvertUtils.isEmpty(targetStatus)) {
return;
}
MesXslMixerPsCompile entity = getById(psId.trim());
if (entity == null || oConvertUtils.isEmpty(entity.getPsCode())) {
return;
}
Date now = operatorTime != null ? operatorTime : new Date();
// 操作人/时间以审批上下文为准写入关联示方(源单痕迹由注册中心双写)
fillWorkflowInfo(entity, targetStatus, operatorName, now);
mesXslFormulaSpecService.syncFromMixerPsWorkflow(entity, targetStatus);
mesXslMixingSpecService.syncFromMixerPsWorkflow(entity, targetStatus);
if ("approve".equals(targetStatus)
&& XslMesBizConstants.PS_TYPE_RAW_INSPECT_STD.equals(entity.getPsType())) {
mesXslRubberQuickTestStdService.markAuditApprovedByPsCompileIds(Collections.singletonList(entity.getId()));
}
}
@Override
public void cascadeRelatedAfterStageRevert(String psId, String previousStatus, String targetStatus) {
if (oConvertUtils.isEmpty(psId) || oConvertUtils.isEmpty(targetStatus)) {
return;
}
MesXslMixerPsCompile entity = getById(psId.trim());
if (entity == null || oConvertUtils.isEmpty(entity.getPsCode())) {
return;
}
entity.setStatus(targetStatus);
mesXslFormulaSpecService.revertFromMixerPsWorkflow(entity, targetStatus);
mesXslMixingSpecService.revertFromMixerPsWorkflow(entity, targetStatus);
if ("approve".equals(previousStatus)
&& XslMesBizConstants.PS_TYPE_RAW_INSPECT_STD.equals(entity.getPsType())) {
mesXslRubberQuickTestStdService.markAuditDraftByPsCompileIds(Collections.singletonList(entity.getId()));
}
}
//update-end---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
}

View File

@@ -189,15 +189,18 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
//update-end---author:cursor ---date:20260526 for【配方日志查询】混炼示方删除落库修改日志-----------
clearChildrenBatch(ids);
this.removeByIds(ids);
Set<String> specNames = new LinkedHashSet<>();
for (MesXslMixingSpec main : mains) {
if (main != null && StringUtils.isNotBlank(main.getSpecName())) {
specNames.add(main.getSpecName().trim());
}
}
for (String specName : specNames) {
syncDeleteGeneratedRubberMixerMaterial(specName);
}
//update-begin---author:jiangxh ---date:20260730 for【混炼示方删除】停用同步删除胶料信息-----------
// 胶料改为手工维护并从列表匹配,删除混炼示方时不再同步删除胶料信息
// Set<String> specNames = new LinkedHashSet<>();
// for (MesXslMixingSpec main : mains) {
// if (main != null && StringUtils.isNotBlank(main.getSpecName())) {
// specNames.add(main.getSpecName().trim());
// }
// }
// for (String specName : specNames) {
// syncDeleteGeneratedRubberMixerMaterial(specName);
// }
//update-end---author:jiangxh ---date:20260730 for【混炼示方删除】停用同步删除胶料信息-----------
//update-end---author:cursor ---date:20260525 for【XSLMES-20260525-A56】混炼示方批量删除性能优化-----------
}
@@ -421,6 +424,13 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
if (CollectionUtils.isEmpty(materialList)) {
return;
}
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
for (MesXslMixingSpecMaterial row : materialList) {
if (row != null && row.getUnitWeight() != null) {
row.setUnitWeight(row.getUnitWeight().setScale(3, java.math.RoundingMode.HALF_UP));
}
}
//update-end---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
//update-begin---author:cursor ---date:20260525 for【XSLMES-20260525-A41】橡胶及配合剂明细累计按种类分组合计-----------
fillMaterialAccumWeight(materialList);
//update-end---author:cursor ---date:20260525 for【XSLMES-20260525-A41】橡胶及配合剂明细累计按种类分组合计-----------
@@ -653,7 +663,12 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
}
for (int rowIndex = index; rowIndex < groupEnd; rowIndex++) {
if (rowIndex == groupEnd - 1) {
materials.get(rowIndex).setAccumWeight(sum.compareTo(BigDecimal.ZERO) != 0 ? sum : null);
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
materials.get(rowIndex).setAccumWeight(
sum.compareTo(BigDecimal.ZERO) != 0
? sum.setScale(3, java.math.RoundingMode.HALF_UP)
: null);
//update-end---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
} else {
materials.get(rowIndex).setAccumWeight(null);
}
@@ -757,11 +772,16 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
//update-end---author:GHT ---date:2026-06-10 for【混炼示方】TCU是否附加为否时清空重量-----------
//update-begin---author:cursor ---date:20260601 for【XSLMES-20260601-A62】删除混炼示方时同步删除自动生成的B/F段胶料信息-----------
//update-begin---author:jiangxh ---date:20260730 for【混炼示方删除】停用同步删除胶料信息方法保留备查-----------
/**
* 删除混炼示方后,若该 B/F 段胶示方编号已无其它混炼示方、未被其它示方明细引用、且未被配合示方选作胶料代号,
* 则同步删除生成时写入的「胶料信息」(mes_material)。仅处理 F 段或 B+数字 形态的自动生成编号,避免误删人工维护胶料
* 删除混炼示方后同步删除胶料信息 —— 已停用。
* 原逻辑:若 B/F 段胶示方编号已无其它混炼示方引用,则删除 mes_material
* 现胶料改为手工维护匹配,删除混炼示方不再动胶料信息。
*/
@SuppressWarnings("unused")
private void syncDeleteGeneratedRubberMixerMaterial(String specName) {
// 已停用:不再同步删除胶料
/*
if (StringUtils.isBlank(specName)) {
return;
}
@@ -800,7 +820,9 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
}
mesMaterialService.removeById(material.getId());
log.info("[混炼示方删除] 同步删除胶料信息 id={}, code={}", material.getId(), specCode);
*/
}
//update-end---author:jiangxh ---date:20260730 for【混炼示方删除】停用同步删除胶料信息方法保留备查-----------
/** 判断是否为生成混炼示方时自动同步的 B/F 段胶示方编号true=F段false=B段null=非自动生成胶料编号 */
private Boolean resolveGeneratedRubberSegment(String specCode) {
@@ -859,16 +881,25 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
wrapper.eq(MesXslMixingSpec::getIssueNumber, ps.getPsCode());
switch (mixerPsTargetStatus) {
case "proofread":
wrapper.set(MesXslMixingSpec::getProofreadBy, ps.getProofreadBy())
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
wrapper.set(MesXslMixingSpec::getStatus, "submit")
.set(MesXslMixingSpec::getProofreadBy, ps.getProofreadBy())
.set(MesXslMixingSpec::getProofreadTime, ps.getProofreadTime());
//update-end---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
break;
case "audit":
wrapper.set(MesXslMixingSpec::getAuditBy, ps.getAuditBy())
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
wrapper.set(MesXslMixingSpec::getStatus, "review_pass")
.set(MesXslMixingSpec::getAuditBy, ps.getAuditBy())
.set(MesXslMixingSpec::getAuditTime, ps.getAuditTime());
//update-end---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
break;
case "approve":
wrapper.set(MesXslMixingSpec::getApproveBy, ps.getApproveBy())
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
wrapper.set(MesXslMixingSpec::getStatus, "recognition_pass")
.set(MesXslMixingSpec::getApproveBy, ps.getApproveBy())
.set(MesXslMixingSpec::getApproveTime, ps.getApproveTime());
//update-end---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
break;
default:
return;
@@ -888,19 +919,28 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
wrapper.eq(MesXslMixingSpec::getIssueNumber, ps.getPsCode());
switch (mixerPsTargetStatus) {
case "compile":
// 回退到编制:清空 校对/审核/批准 三组痕迹
wrapper.set(MesXslMixingSpec::getProofreadBy, null).set(MesXslMixingSpec::getProofreadTime, null)
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
// 回退到编制:状态回 compile清空 校对/审核/批准 三组痕迹
wrapper.set(MesXslMixingSpec::getStatus, "compile")
.set(MesXslMixingSpec::getProofreadBy, null).set(MesXslMixingSpec::getProofreadTime, null)
.set(MesXslMixingSpec::getAuditBy, null).set(MesXslMixingSpec::getAuditTime, null)
.set(MesXslMixingSpec::getApproveBy, null).set(MesXslMixingSpec::getApproveTime, null);
//update-end---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
break;
case "proofread":
// 回退到校对:清空 审核/批准 痕迹(保留校对)
wrapper.set(MesXslMixingSpec::getAuditBy, null).set(MesXslMixingSpec::getAuditTime, null)
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
// 回退到校对:状态回 submit清空 审核/批准 痕迹(保留校对)
wrapper.set(MesXslMixingSpec::getStatus, "submit")
.set(MesXslMixingSpec::getAuditBy, null).set(MesXslMixingSpec::getAuditTime, null)
.set(MesXslMixingSpec::getApproveBy, null).set(MesXslMixingSpec::getApproveTime, null);
//update-end---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
break;
case "audit":
// 回退到审核:清空 批准 痕迹(保留校对/审核)
wrapper.set(MesXslMixingSpec::getApproveBy, null).set(MesXslMixingSpec::getApproveTime, null);
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
// 回退到审核:状态回 review_pass清空 批准 痕迹(保留校对/审核)
wrapper.set(MesXslMixingSpec::getStatus, "review_pass")
.set(MesXslMixingSpec::getApproveBy, null).set(MesXslMixingSpec::getApproveTime, null);
//update-end---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
break;
default:
return;

View File

@@ -24,7 +24,7 @@ import java.util.Map;
@Slf4j
@SpringBootApplication(
exclude = MongoAutoConfiguration.class,
scanBasePackages = {"org.jeecg"}
scanBasePackages = {"org.jeecg"}
)
@ImportAutoConfiguration(JustAuthAutoConfiguration.class) // spring boot 3.x justauth 兼容性处理
public class JeecgSystemApplication extends SpringBootServletInitializer {

View File

@@ -134,7 +134,11 @@ export const materialColumns: JVxeColumn[] = [
minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH,
},
{ title: '密炼物料描述', key: 'mixerMaterialDesc', type: JVxeTypes.input, width: 220, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH },
{ title: '单重', key: 'unitWeight', type: JVxeTypes.inputNumber, width: 72, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH, align: 'center' },
{ title: '单重', key: 'unitWeight', type: JVxeTypes.inputNumber, width: 72, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH, align: 'center',
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
props: { precision: 3 },
//update-end---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
},
//update-begin---author:cursor ---date:20260525 for【XSLMES-20260525-A41】累计列按种类分组合计只读展示-----------
{
title: '累计',
@@ -144,6 +148,9 @@ export const materialColumns: JVxeColumn[] = [
minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH,
align: 'center',
disabled: true,
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
props: { precision: 3 },
//update-end---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
},
//update-end---author:cursor ---date:20260525 for【XSLMES-20260525-A41】累计列按种类分组合计只读展示-----------
{ title: '顺序', key: 'seqNo', type: JVxeTypes.inputNumber, width: 64, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH, align: 'center' },
@@ -297,8 +304,10 @@ export function fillMixingMaterialAccumWeight(rows: Recordable[] = []): Recordab
groupEnd++;
}
for (let rowIndex = index; rowIndex < groupEnd; rowIndex++) {
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
rows[rowIndex].accumWeight =
rowIndex === groupEnd - 1 && sum !== 0 ? roundMixingMaterialNumber(sum) : null;
rowIndex === groupEnd - 1 && sum !== 0 ? roundMixingMaterialAccumNumber(sum) : null;
//update-end---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
}
index = groupEnd;
}
@@ -315,7 +324,14 @@ function toMixingMaterialNumber(value: unknown): number | null {
}
/** 混炼示方重量小数位(与后端 BigDecimal 精度一致) */
const MIXING_MATERIAL_WEIGHT_SCALE = 6;
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
const MIXING_MATERIAL_WEIGHT_SCALE = 3;
//update-end---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
/** 累计列小数位 */
const MIXING_MATERIAL_ACCUM_WEIGHT_SCALE = 3;
//update-end---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
//update-begin---author:cursor ---date:20260526 for【XSLMES-20260526-A60】换算系数/配方参数数值展示优化-----------
/** 换算系数展示小数位 */
@@ -401,6 +417,22 @@ function roundMixingMaterialNumber(value: number): number {
return Number(value.toFixed(MIXING_MATERIAL_WEIGHT_SCALE));
}
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
/** 累计重量四舍五入为三位小数 */
function roundMixingMaterialAccumNumber(value: number): number {
return Number(value.toFixed(MIXING_MATERIAL_ACCUM_WEIGHT_SCALE));
}
/** 格式化累计重量展示文本 */
function formatMixingMaterialAccumWeight(value: unknown): string {
const num = toMixingMaterialNumber(value);
if (num == null) {
return '';
}
return String(roundMixingMaterialAccumNumber(num));
}
//update-end---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
/** 格式化重量展示文本 */
function formatMixingMaterialWeight(value: unknown): string {
const num = toMixingMaterialNumber(value);
@@ -593,7 +625,9 @@ export function buildMixingMaterialFooterCells(
return { key, width, text: formatTotal(totals.unitWeight), align: 'center', isTotal: true };
}
if (key === 'accumWeight') {
return { key, width, text: formatTotal(totals.accumWeight), align: 'center', isTotal: true };
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
return { key, width, text: formatMixingMaterialAccumWeight(totals.accumWeight), align: 'center', isTotal: true };
//update-end---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
}
const isLabelCol = unitWeightIndex > 0 && index === unitWeightIndex - 1;
return {

View File

@@ -526,7 +526,10 @@ public class RawMaterialEntryEditDialogViewModel : BaseViewModel, IDialogResulta
.Initialize<WeightRecordPickerDialogViewModel>(vm =>
{
pickerVm = vm;
vm.Initialize(Entry?.BillNo);
vm.Initialize(
Entry?.BillNo,
SelectedMaterial?.Id ?? Entry?.MaterialId,
SelectedMaterial?.MaterialName ?? Entry?.MaterialName);
})
.GetResultAsync<bool>());
}

View File

@@ -24,6 +24,26 @@ public class WeightRecordPickerDialogViewModel : BaseViewModel, IDialogResultabl
set => SetProperty(ref _searchPlateNumber, value);
}
/// <summary>入场记录已选密炼物料ID有值时仅展示关联该物料的磅单。</summary>
private string? _filterMixerMaterialId;
private string? _filterMixerMaterialName;
public string FilterHint
{
get
{
if (string.IsNullOrWhiteSpace(_filterMixerMaterialId))
{
return "未选择密炼物料时显示全部进厂磅单;已选物料时仅匹配含该物料的磅单。";
}
var name = string.IsNullOrWhiteSpace(_filterMixerMaterialName)
? _filterMixerMaterialId
: _filterMixerMaterialName;
return $"已按密炼物料「{name}」自动匹配关联磅单";
}
}
public ObservableCollection<MesXslWeightRecord> Records { get; } = new();
private MesXslWeightRecord? _selectedRecord;
@@ -40,7 +60,7 @@ public class WeightRecordPickerDialogViewModel : BaseViewModel, IDialogResultabl
}
public string SelectedRecordDisplay => _selectedRecord != null
? $"[{_selectedRecord.BillNo}] 供应商:{_selectedRecord.SenderUnit ?? "-"}"
? $"[{_selectedRecord.BillNo}] 供应商:{_selectedRecord.SenderUnit ?? "-"} 物料:{_selectedRecord.MixerMaterialNames ?? "-"}"
: "选中榜单后点击「确认选择」";
public bool HasSelectedRecord => _selectedRecord != null;
@@ -67,16 +87,24 @@ public class WeightRecordPickerDialogViewModel : BaseViewModel, IDialogResultabl
SearchCommand = new DelegateCommand(async () => await LoadAsync());
ConfirmCommand = new DelegateCommand(Confirm, () => SelectedRecord != null);
CancelCommand = new DelegateCommand(() => CloseAction?.Invoke());
_ = LoadAsync();
// 不在构造时加载:等 Initialize 带入密炼物料过滤条件后再查,避免竞态覆盖筛选结果
}
public void Initialize(string? billNo)
/// <param name="billNo">已选榜单号(用于回显搜索)</param>
/// <param name="mixerMaterialId">已选密炼物料ID有值则只匹配含该物料的磅单</param>
/// <param name="mixerMaterialName">密炼物料名称(提示展示)</param>
public void Initialize(string? billNo, string? mixerMaterialId = null, string? mixerMaterialName = null)
{
_filterMixerMaterialId = string.IsNullOrWhiteSpace(mixerMaterialId) ? null : mixerMaterialId.Trim();
_filterMixerMaterialName = string.IsNullOrWhiteSpace(mixerMaterialName) ? null : mixerMaterialName.Trim();
RaisePropertyChanged(nameof(FilterHint));
if (!string.IsNullOrWhiteSpace(billNo))
{
SearchBillNo = billNo.Trim();
_ = LoadAsync();
}
_ = LoadAsync();
}
private async Task LoadAsync()
@@ -92,7 +120,7 @@ public class WeightRecordPickerDialogViewModel : BaseViewModel, IDialogResultabl
filterInoutDirection: "1");
Records.Clear();
foreach (var record in result.Records)
foreach (var record in result.Records.Where(MatchesSelectedMixerMaterial))
{
Records.Add(record);
}
@@ -102,6 +130,11 @@ public class WeightRecordPickerDialogViewModel : BaseViewModel, IDialogResultabl
SelectedRecord = Records.FirstOrDefault(x =>
string.Equals(x.BillNo, SearchBillNo, StringComparison.OrdinalIgnoreCase));
}
else if (!string.IsNullOrWhiteSpace(_filterMixerMaterialId) && Records.Count == 1)
{
// 仅匹配到一条时自动选中,便于快速确认
SelectedRecord = Records[0];
}
}
catch
{
@@ -113,6 +146,25 @@ public class WeightRecordPickerDialogViewModel : BaseViewModel, IDialogResultabl
}
}
/// <summary>未指定物料时不过滤;指定时要求磅单 MixerMaterialIds 含该ID。</summary>
private bool MatchesSelectedMixerMaterial(MesXslWeightRecord record)
{
if (string.IsNullOrWhiteSpace(_filterMixerMaterialId))
{
return true;
}
if (string.IsNullOrWhiteSpace(record.MixerMaterialIds))
{
return false;
}
var parts = record.MixerMaterialIds.Split(
new[] { ';', ',', '', '' },
StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
return parts.Any(p => string.Equals(p, _filterMixerMaterialId, StringComparison.OrdinalIgnoreCase));
}
private void Confirm()
{
if (SelectedRecord == null)

View File

@@ -34,6 +34,44 @@ public class WeightRecordEditDialogViewModel : BaseViewModel, IDialogResultable<
public bool IsAddMode => string.IsNullOrWhiteSpace(Record?.Id);
public string DialogTitle => IsAddMode ? "新增磅单" : "编辑磅单";
/// <summary>毛重输入:变更后自动重算净重</summary>
public double? GrossWeightInput
{
get => Record?.GrossWeight;
set
{
if (Record == null || Nullable.Equals(Record.GrossWeight, value)) return;
Record.GrossWeight = value;
RaisePropertyChanged(nameof(GrossWeightInput));
RecalcNetWeight();
}
}
/// <summary>皮重输入:变更后自动用毛重-皮重填充净重</summary>
public double? TareWeightInput
{
get => Record?.TareWeight;
set
{
if (Record == null || Nullable.Equals(Record.TareWeight, value)) return;
Record.TareWeight = value;
RaisePropertyChanged(nameof(TareWeightInput));
RecalcNetWeight();
}
}
/// <summary>净重(只读展示,由毛重/皮重自动计算)</summary>
public double? NetWeightInput
{
get => Record?.NetWeight;
private set
{
if (Record == null || Nullable.Equals(Record.NetWeight, value)) return;
Record.NetWeight = value;
RaisePropertyChanged(nameof(NetWeightInput));
}
}
public ObservableCollection<KeyValuePair<string, string>> InoutDirectionOptions { get; } = new();
private bool _result;
@@ -121,6 +159,7 @@ public class WeightRecordEditDialogViewModel : BaseViewModel, IDialogResultable<
};
RaisePropertyChanged(nameof(IsAddMode));
RaisePropertyChanged(nameof(DialogTitle));
RaiseWeightInputsChanged();
}
public void InitializeForEdit(MesXslWeightRecord record)
@@ -151,6 +190,31 @@ public class WeightRecordEditDialogViewModel : BaseViewModel, IDialogResultable<
RaisePropertyChanged(nameof(HasSelectedMixerMaterials));
RaisePropertyChanged(nameof(IsAddMode));
RaisePropertyChanged(nameof(DialogTitle));
RaiseWeightInputsChanged();
// 编辑打开时若已有毛重+皮重,立即校正净重展示
RecalcNetWeight();
}
private void RaiseWeightInputsChanged()
{
RaisePropertyChanged(nameof(GrossWeightInput));
RaisePropertyChanged(nameof(TareWeightInput));
RaisePropertyChanged(nameof(NetWeightInput));
}
/// <summary>毛重、皮重均有效时:净重 = 毛重 - 皮重(保留两位小数)</summary>
private void RecalcNetWeight()
{
if (Record == null) return;
if (Record.GrossWeight.HasValue && Record.GrossWeight.Value > 0
&& Record.TareWeight.HasValue && Record.TareWeight.Value > 0)
{
NetWeightInput = Math.Round(Record.GrossWeight.Value - Record.TareWeight.Value, 2);
}
else
{
NetWeightInput = null;
}
}
private async Task SaveAsync()
@@ -168,12 +232,8 @@ public class WeightRecordEditDialogViewModel : BaseViewModel, IDialogResultable<
return;
}
// 净重自动计算0 视为未称,不计算净重)
if (Record.GrossWeight.HasValue && Record.GrossWeight.Value > 0
&& Record.TareWeight.HasValue && Record.TareWeight.Value > 0)
Record.NetWeight = Math.Round(Record.GrossWeight.Value - Record.TareWeight.Value, 2);
else
Record.NetWeight = null;
// 保存前再算一次,防止未触发属性变更时净重未更新
RecalcNetWeight();
// 写入密炼物料
Record.MixerMaterialIds = _mixerMaterialIds;

View File

@@ -8,10 +8,11 @@
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d"
Width="760">
Width="920">
<Grid Background="{DynamicResource ThirdlyRegionBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="360"/>
@@ -34,7 +35,11 @@
Padding="0" HorizontalAlignment="Right" VerticalAlignment="Center"/>
</hc:SimplePanel>
<Border Grid.Row="1" Background="{DynamicResource RegionBrush}" Padding="16,10">
<TextBlock Grid.Row="1" Margin="20,0,20,8" FontSize="12"
Foreground="{DynamicResource SecondaryTextBrush}"
Text="{Binding FilterHint}" TextWrapping="Wrap"/>
<Border Grid.Row="2" Background="{DynamicResource RegionBrush}" Padding="16,10">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
@@ -70,7 +75,7 @@
</Border>
<DataGrid x:Name="WeightRecordsGrid"
Grid.Row="2"
Grid.Row="3"
Margin="16,8,16,0"
ItemsSource="{Binding Records}"
SelectedItem="{Binding SelectedRecord}"
@@ -135,20 +140,21 @@
</Style>
</DataGrid.CellStyle>
<DataGrid.Columns>
<DataGridTextColumn Header="榜单号" Binding="{Binding BillNo}" Width="180"/>
<DataGridTextColumn Header="车牌号" Binding="{Binding PlateNumber}" Width="100"/>
<DataGridTextColumn Header="榜单号" Binding="{Binding BillNo}" Width="160"/>
<DataGridTextColumn Header="车牌号" Binding="{Binding PlateNumber}" Width="90"/>
<DataGridTextColumn Header="密炼物料" Binding="{Binding MixerMaterialNames}" Width="160"/>
<DataGridTextColumn Header="供应商(发货单位)" Binding="{Binding SenderUnit}" Width="*"/>
<DataGridTextColumn Header="净重(KG)" Binding="{Binding NetWeight, StringFormat=N2}" Width="90"/>
<DataGridTextColumn Header="已入场(KG)" Binding="{Binding EnteredWeight, StringFormat=N2}" Width="100"/>
<DataGridTextColumn Header="货物皮重" Binding="{Binding CargoTareWeight, StringFormat=N2}" Width="90"/>
<DataGridTextColumn Header="称重日期" Binding="{Binding WeighDate, StringFormat='yyyy-MM-dd'}" Width="110"/>
<DataGridTextColumn Header="净重(KG)" Binding="{Binding NetWeight, StringFormat=N2}" Width="80"/>
<DataGridTextColumn Header="已入场(KG)" Binding="{Binding EnteredWeight, StringFormat=N2}" Width="90"/>
<DataGridTextColumn Header="货物皮重" Binding="{Binding CargoTareWeight, StringFormat=N2}" Width="80"/>
<DataGridTextColumn Header="称重日期" Binding="{Binding WeighDate, StringFormat='yyyy-MM-dd'}" Width="100"/>
</DataGrid.Columns>
</DataGrid>
<Border Grid.Row="3" BorderBrush="{DynamicResource BorderBrush}" BorderThickness="0,1,0,0"
<Border Grid.Row="4" BorderBrush="{DynamicResource BorderBrush}" BorderThickness="0,1,0,0"
Padding="16,12">
<Grid>
<TextBlock VerticalAlignment="Center" FontSize="13" MaxWidth="420"
<TextBlock VerticalAlignment="Center" FontSize="13" MaxWidth="560"
TextTrimming="CharacterEllipsis" HorizontalAlignment="Left"
Text="{Binding SelectedRecordDisplay}">
<TextBlock.Style>

View File

@@ -144,7 +144,7 @@
<!-- 毛重 -->
<hc:Col Span="12">
<hc:NumericUpDown Value="{Binding Record.GrossWeight}"
<hc:NumericUpDown Value="{Binding GrossWeightInput, UpdateSourceTrigger=PropertyChanged}"
Minimum="0"
DecimalPlaces="2"
Style="{StaticResource NumericUpDownPlus}"
@@ -158,7 +158,7 @@
<!-- 皮重 -->
<hc:Col Span="12">
<hc:NumericUpDown Value="{Binding Record.TareWeight}"
<hc:NumericUpDown Value="{Binding TareWeightInput, UpdateSourceTrigger=PropertyChanged}"
Minimum="0"
DecimalPlaces="2"
Style="{StaticResource NumericUpDownPlus}"
@@ -170,17 +170,18 @@
Margin="0,0,0,16"/>
</hc:Col>
<!-- 净重(只读 -->
<!-- 净重(自动:毛重-皮重 -->
<hc:Col Span="12">
<hc:NumericUpDown Value="{Binding Record.NetWeight}"
<hc:NumericUpDown Value="{Binding NetWeightInput, Mode=OneWay}"
Minimum="0"
DecimalPlaces="2"
Style="{StaticResource NumericUpDownPlus}"
IsEnabled="True"
IsReadOnly="True"
IsEnabled="False"
hc:InfoElement.Title="净重(KG)"
hc:InfoElement.TitleWidth="80"
hc:InfoElement.TitlePlacement="Left"
hc:InfoElement.Placeholder="自动计算"
hc:InfoElement.Placeholder="毛重-皮重自动计算"
Margin="0,0,0,16"/>
</hc:Col>