优化混炼示方,新增种类配置
This commit is contained in:
@@ -186,6 +186,95 @@ jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipm
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingStepSelectCell.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingSpecModal.vue
|
||||
|
||||
-- author:cursor---date:20260522--for: 【XSLMES-20260522-A37】未选机台点击动作/组合提示请先选择机台 ---
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingStepSelectCell.vue
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A43】混炼示方换算系数联动橡胶及配合剂单重实时计算 ---
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingSpecModal.vue
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A42】混炼示方橡胶及配合剂明细底部固定合计行 ---
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingSpecModal.vue
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A41】混炼示方橡胶及配合剂明细累计按种类分组合计 ---
|
||||
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
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingSpecModal.vue
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A44】配合示方生成混炼示方时按设备台账有效体积自动计算填充体积 ---
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipmentLedgerMultiSelectModal.vue
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A45】混炼示方保存/批量生成子表改批量插入并延长前端超时 ---
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixingSpecServiceImpl.java
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.api.ts
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.api.ts
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A46】混炼示方换算系数/单重/机台有效体积联动填充体积 ---
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingSpecModal.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipmentLedgerSelectModal.vue
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A47】混炼示方保存分步骤性能诊断日志 ---
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixingSpecServiceImpl.java
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslMixingSpecController.java
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A48】生成混炼示方时同步B/F段胶至密炼物料(母炼胶/A胶、终炼胶/Q胶) ---
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A49】删除混炼示方时同步删除B/F段胶密炼物料 ---
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixingSpecServiceImpl.java
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A50】MES物料小类胶料标记/生成混炼示方种类映射/混炼示方选料弹窗 ---
|
||||
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysCategoryServiceImpl.java
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
|
||||
jeecgboot-vue3/src/views/system/category/category.constants.ts
|
||||
jeecgboot-vue3/src/views/system/category/category.data.ts
|
||||
jeecgboot-vue3/src/views/system/category/components/CategoryModal.vue
|
||||
jeecgboot-vue3/src/views/mes/material/modules/MesMixerMaterialSysCategoryModal.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingSpecModal.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingMaterialSelectModal.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingMaterialCategorySetting.vue
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A50】选料弹窗左侧小类树为空修复(对齐密炼物料列表树加载/异步展开/隐藏配置重置) ---
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingMaterialSelectModal.vue
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A50】选料弹窗小类设置无明细/统一分类加载函数 -----------
|
||||
jeecgboot-vue3/src/views/system/category/category.constants.ts
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingMaterialSelectModal.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingMaterialCategorySetting.vue
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A50】选料弹窗分类加载改为getChildListBatch两级查询 -----------
|
||||
jeecgboot-vue3/src/views/system/category/category.constants.ts
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A50】选料弹窗openModal未传data导致初始化未执行 -----------
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingMaterialSelectModal.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingSpecModal.vue
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A50】选料弹窗移出父Modal+useModalInner初始化 -----------
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingSpecModal.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingMaterialSelectModal.vue
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A50】小类展示分组勾选互不覆盖 -----------
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingMaterialCategorySetting.vue
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A50】选料弹窗隐藏ERP列并新增自动/人工称量列 -----------
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingMaterialSelectModal.vue
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A51】密炼物料种类配置表及列表批量新增 -----------
|
||||
jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_102__mes_xsl_mixer_material_kind_cfg.sql
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslMixerMaterialKindCfg.java
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslMixerMaterialKindCfgMapper.java
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslMixerMaterialKindCfgService.java
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixerMaterialKindCfgServiceImpl.java
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslMixerMaterialKindCfgController.java
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixerMaterialKindCfg/MesXslMixerMaterialKindCfgList.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixerMaterialKindCfg/MesXslMixerMaterialKindCfg.data.ts
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixerMaterialKindCfg/MesXslMixerMaterialKindCfg.api.ts
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixerMaterialKindCfg/components/MesXslMixerMaterialKindCfgBatchModal.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixerMaterialKindCfg/components/MesXslMixerMaterialKindCfgEditModal.vue
|
||||
|
||||
-- author:cursor---date:20260525--for: 【XSLMES-20260525-A51】密炼物料种类配置菜单ID冲突修复 -----------
|
||||
jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_102__mes_xsl_mixer_material_kind_cfg.sql
|
||||
jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_103__mes_xsl_mixer_material_kind_cfg_menu_fix.sql
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.boot3</groupId>
|
||||
<artifactId>jeecg-boot-base-core</artifactId>
|
||||
<version>${jeecgboot.version}</version>
|
||||
</dependency>
|
||||
<!-- 复用打印模板模块:打印机枚举、业务绑定、PDF 提交队列 -->
|
||||
<dependency>
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
package org.jeecg.modules.xslmes.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.system.base.controller.JeecgController;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslMixerMaterialKindCfg;
|
||||
import org.jeecg.modules.xslmes.service.IMesXslMixerMaterialKindCfgService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* MES 密炼物料种类配置
|
||||
*/
|
||||
@Tag(name = "MES密炼物料种类配置")
|
||||
@RestController
|
||||
@RequestMapping("/xslmes/mesXslMixerMaterialKindCfg")
|
||||
@Slf4j
|
||||
public class MesXslMixerMaterialKindCfgController
|
||||
extends JeecgController<MesXslMixerMaterialKindCfg, IMesXslMixerMaterialKindCfgService> {
|
||||
|
||||
@Autowired
|
||||
private IMesXslMixerMaterialKindCfgService mesXslMixerMaterialKindCfgService;
|
||||
|
||||
@Operation(summary = "MES密炼物料种类配置-分页列表查询")
|
||||
@GetMapping(value = "/list")
|
||||
public Result<IPage<MesXslMixerMaterialKindCfg>> queryPageList(
|
||||
MesXslMixerMaterialKindCfg model,
|
||||
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
|
||||
HttpServletRequest req) {
|
||||
QueryWrapper<MesXslMixerMaterialKindCfg> queryWrapper = QueryGenerator.initQueryWrapper(model, req.getParameterMap());
|
||||
queryWrapper.orderByAsc("priority").orderByDesc("create_time");
|
||||
Page<MesXslMixerMaterialKindCfg> page = new Page<>(pageNo, pageSize);
|
||||
IPage<MesXslMixerMaterialKindCfg> pageList = mesXslMixerMaterialKindCfgService.page(page, queryWrapper);
|
||||
return Result.OK(pageList);
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A51】密炼物料种类配置展开与批量保存-----------
|
||||
@Operation(summary = "MES密炼物料种类配置-按根字典/分类展开明细")
|
||||
@GetMapping(value = "/expandLines")
|
||||
public Result<List<MesXslMixerMaterialKindCfg>> expandLines(
|
||||
@RequestParam(name = "sourceType") String sourceType,
|
||||
@RequestParam(name = "sourceRootCode") String sourceRootCode,
|
||||
@RequestParam(name = "tenantId", required = false) Integer tenantId) {
|
||||
List<MesXslMixerMaterialKindCfg> lines =
|
||||
mesXslMixerMaterialKindCfgService.expandLines(sourceType, sourceRootCode, tenantId);
|
||||
return Result.OK(lines);
|
||||
}
|
||||
|
||||
@AutoLog(value = "MES密炼物料种类配置-批量添加")
|
||||
@Operation(summary = "MES密炼物料种类配置-批量添加")
|
||||
@RequiresPermissions("xslmes:mes_xsl_mixer_material_kind_cfg:add")
|
||||
@PostMapping(value = "/addBatch")
|
||||
public Result<String> addBatch(@RequestBody List<MesXslMixerMaterialKindCfg> lines) {
|
||||
mesXslMixerMaterialKindCfgService.saveBatchLines(lines, null);
|
||||
return Result.OK("添加成功!");
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A51】密炼物料种类配置展开与批量保存-----------
|
||||
|
||||
@AutoLog(value = "MES密炼物料种类配置-添加")
|
||||
@Operation(summary = "MES密炼物料种类配置-添加")
|
||||
@RequiresPermissions("xslmes:mes_xsl_mixer_material_kind_cfg:add")
|
||||
@PostMapping(value = "/add")
|
||||
public Result<String> add(@RequestBody MesXslMixerMaterialKindCfg model) {
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A51】密炼物料种类配置保存校验-----------
|
||||
String err = validateForSave(model, false);
|
||||
if (err != null) {
|
||||
return Result.error(err);
|
||||
}
|
||||
model.setDelFlag(CommonConstant.DEL_FLAG_0);
|
||||
mesXslMixerMaterialKindCfgService.save(model);
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A51】密炼物料种类配置保存校验-----------
|
||||
return Result.OK("添加成功!");
|
||||
}
|
||||
|
||||
@AutoLog(value = "MES密炼物料种类配置-编辑")
|
||||
@Operation(summary = "MES密炼物料种类配置-编辑")
|
||||
@RequiresPermissions("xslmes:mes_xsl_mixer_material_kind_cfg:edit")
|
||||
@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
|
||||
public Result<String> edit(@RequestBody MesXslMixerMaterialKindCfg model) {
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A51】密炼物料种类配置保存校验-----------
|
||||
String err = validateForSave(model, true);
|
||||
if (err != null) {
|
||||
return Result.error(err);
|
||||
}
|
||||
mesXslMixerMaterialKindCfgService.updateById(model);
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A51】密炼物料种类配置保存校验-----------
|
||||
return Result.OK("编辑成功!");
|
||||
}
|
||||
|
||||
@AutoLog(value = "MES密炼物料种类配置-删除")
|
||||
@Operation(summary = "MES密炼物料种类配置-通过id删除")
|
||||
@RequiresPermissions("xslmes:mes_xsl_mixer_material_kind_cfg:delete")
|
||||
@DeleteMapping(value = "/delete")
|
||||
public Result<String> delete(@RequestParam(name = "id", required = true) String id) {
|
||||
mesXslMixerMaterialKindCfgService.removeById(id);
|
||||
return Result.OK("删除成功!");
|
||||
}
|
||||
|
||||
@AutoLog(value = "MES密炼物料种类配置-批量删除")
|
||||
@Operation(summary = "MES密炼物料种类配置-批量删除")
|
||||
@RequiresPermissions("xslmes:mes_xsl_mixer_material_kind_cfg:deleteBatch")
|
||||
@DeleteMapping(value = "/deleteBatch")
|
||||
public Result<String> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
|
||||
mesXslMixerMaterialKindCfgService.removeByIds(Arrays.asList(ids.split(",")));
|
||||
return Result.OK("批量删除成功!");
|
||||
}
|
||||
|
||||
@Operation(summary = "MES密炼物料种类配置-通过id查询")
|
||||
@GetMapping(value = "/queryById")
|
||||
public Result<MesXslMixerMaterialKindCfg> queryById(@RequestParam(name = "id", required = true) String id) {
|
||||
MesXslMixerMaterialKindCfg entity = mesXslMixerMaterialKindCfgService.getById(id);
|
||||
if (entity == null) {
|
||||
return Result.error("未找到对应数据");
|
||||
}
|
||||
return Result.OK(entity);
|
||||
}
|
||||
|
||||
@RequiresPermissions("xslmes:mes_xsl_mixer_material_kind_cfg:exportXls")
|
||||
@RequestMapping(value = "/exportXls")
|
||||
public ModelAndView exportXls(HttpServletRequest request, MesXslMixerMaterialKindCfg model) {
|
||||
return super.exportXls(request, model, MesXslMixerMaterialKindCfg.class, "密炼物料种类配置");
|
||||
}
|
||||
|
||||
@RequiresPermissions("xslmes:mes_xsl_mixer_material_kind_cfg:importExcel")
|
||||
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
|
||||
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
|
||||
return super.importExcel(request, response, MesXslMixerMaterialKindCfg.class);
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A51】密炼物料种类配置保存校验-----------
|
||||
private String validateForSave(MesXslMixerMaterialKindCfg model, boolean isUpdate) {
|
||||
if (model == null) {
|
||||
return "参数不能为空";
|
||||
}
|
||||
if (oConvertUtils.isEmpty(model.getKindKey())) {
|
||||
return "种类键值不能为空";
|
||||
}
|
||||
if (oConvertUtils.isEmpty(model.getKindName())) {
|
||||
return "种类名称不能为空";
|
||||
}
|
||||
if (oConvertUtils.isEmpty(model.getSourceType())) {
|
||||
return "数据源类型不能为空";
|
||||
}
|
||||
if (oConvertUtils.isEmpty(model.getCategoryRefId())) {
|
||||
return "对应分类不能为空";
|
||||
}
|
||||
if (model.getPriority() == null) {
|
||||
model.setPriority(999);
|
||||
}
|
||||
if (isUpdate && oConvertUtils.isEmpty(model.getId())) {
|
||||
return "主键不能为空";
|
||||
}
|
||||
try {
|
||||
mesXslMixerMaterialKindCfgService.checkDuplicate(model, isUpdate ? model.getId() : null);
|
||||
} catch (Exception e) {
|
||||
return e.getMessage();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A51】密炼物料种类配置保存校验-----------
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||
@@ -30,6 +31,7 @@ import org.springframework.web.servlet.ModelAndView;
|
||||
@Tag(name = "MES混炼示方")
|
||||
@RestController
|
||||
@RequestMapping("/xslmes/mesXslMixingSpec")
|
||||
@Slf4j
|
||||
public class MesXslMixingSpecController extends JeecgController<MesXslMixingSpec, IMesXslMixingSpecService> {
|
||||
|
||||
@Autowired
|
||||
@@ -59,13 +61,36 @@ public class MesXslMixingSpecController extends JeecgController<MesXslMixingSpec
|
||||
@RequiresPermissions("xslmes:mes_xsl_mixing_spec:add")
|
||||
@PostMapping(value = "/add")
|
||||
public Result<String> add(@RequestBody MesXslMixingSpecPage page) {
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
||||
long requestStartMs = System.currentTimeMillis();
|
||||
log.info(
|
||||
"[混炼示方保存性能] 接口/add 收到请求 specName={}, payload=[material={}, step={}, downStep={}, tcu={}]",
|
||||
page != null ? page.getSpecName() : null,
|
||||
countChildRows(page != null ? page.getMaterialList() : null),
|
||||
countChildRows(page != null ? page.getStepList() : null),
|
||||
countChildRows(page != null ? page.getDownStepList() : null),
|
||||
countChildRows(page != null ? page.getTcuList() : null));
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
||||
String err = validateMain(page);
|
||||
if (err != null) {
|
||||
return Result.error(err);
|
||||
}
|
||||
long validateMs = System.currentTimeMillis();
|
||||
MesXslMixingSpec main = new MesXslMixingSpec();
|
||||
BeanUtils.copyProperties(page, main);
|
||||
long copyMs = System.currentTimeMillis();
|
||||
mesXslMixingSpecService.saveMain(main, page.getMaterialList(), page.getStepList(), page.getDownStepList(), page.getTcuList());
|
||||
long serviceMs = System.currentTimeMillis();
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
||||
log.info(
|
||||
"[混炼示方保存性能] 接口/add 完成 specName={}, mainId={}, validate={}ms, copy={}ms, service={}ms, total={}ms(返回响应前,不含AutoLog等切面)",
|
||||
main.getSpecName(),
|
||||
main.getId(),
|
||||
validateMs - requestStartMs,
|
||||
copyMs - validateMs,
|
||||
serviceMs - copyMs,
|
||||
serviceMs - requestStartMs);
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
||||
return Result.OK("添加成功!");
|
||||
}
|
||||
|
||||
@@ -74,13 +99,37 @@ public class MesXslMixingSpecController extends JeecgController<MesXslMixingSpec
|
||||
@RequiresPermissions("xslmes:mes_xsl_mixing_spec:edit")
|
||||
@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
|
||||
public Result<String> edit(@RequestBody MesXslMixingSpecPage page) {
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
||||
long requestStartMs = System.currentTimeMillis();
|
||||
log.info(
|
||||
"[混炼示方保存性能] 接口/edit 收到请求 id={}, specName={}, payload=[material={}, step={}, downStep={}, tcu={}]",
|
||||
page != null ? page.getId() : null,
|
||||
page != null ? page.getSpecName() : null,
|
||||
countChildRows(page != null ? page.getMaterialList() : null),
|
||||
countChildRows(page != null ? page.getStepList() : null),
|
||||
countChildRows(page != null ? page.getDownStepList() : null),
|
||||
countChildRows(page != null ? page.getTcuList() : null));
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
||||
String err = validateMain(page);
|
||||
if (err != null) {
|
||||
return Result.error(err);
|
||||
}
|
||||
long validateMs = System.currentTimeMillis();
|
||||
MesXslMixingSpec main = new MesXslMixingSpec();
|
||||
BeanUtils.copyProperties(page, main);
|
||||
long copyMs = System.currentTimeMillis();
|
||||
mesXslMixingSpecService.updateMain(main, page.getMaterialList(), page.getStepList(), page.getDownStepList(), page.getTcuList());
|
||||
long serviceMs = System.currentTimeMillis();
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
||||
log.info(
|
||||
"[混炼示方保存性能] 接口/edit 完成 id={}, specName={}, validate={}ms, copy={}ms, service={}ms, total={}ms(返回响应前,不含AutoLog等切面)",
|
||||
main.getId(),
|
||||
main.getSpecName(),
|
||||
validateMs - requestStartMs,
|
||||
copyMs - validateMs,
|
||||
serviceMs - copyMs,
|
||||
serviceMs - requestStartMs);
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
||||
return Result.OK("编辑成功!");
|
||||
}
|
||||
|
||||
@@ -151,5 +200,11 @@ public class MesXslMixingSpecController extends JeecgController<MesXslMixingSpec
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
||||
private static int countChildRows(List<?> rows) {
|
||||
return rows == null ? 0 : rows.size();
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】混炼示方主子保存校验-----------
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package org.jeecg.modules.xslmes.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
/**
|
||||
* MES 密炼物料种类配置
|
||||
*/
|
||||
@Data
|
||||
@TableName("mes_xsl_mixer_material_kind_cfg")
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(description = "MES密炼物料种类配置")
|
||||
public class MesXslMixerMaterialKindCfg implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static final String SOURCE_TYPE_DICT = "dict";
|
||||
public static final String SOURCE_TYPE_CATEGORY = "category";
|
||||
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private String id;
|
||||
|
||||
@Excel(name = "种类键值", width = 15)
|
||||
@Schema(description = "种类键值")
|
||||
private String kindKey;
|
||||
|
||||
@Excel(name = "种类名称", width = 20)
|
||||
@Schema(description = "种类名称")
|
||||
private String kindName;
|
||||
|
||||
@Excel(name = "数据源类型", width = 12)
|
||||
@Schema(description = "数据源类型:dict/category")
|
||||
private String sourceType;
|
||||
|
||||
@Excel(name = "根编码", width = 15)
|
||||
@Schema(description = "根字典编码或分类pcode")
|
||||
private String sourceRootCode;
|
||||
|
||||
@Excel(name = "根名称", width = 20)
|
||||
@Schema(description = "根名称冗余")
|
||||
private String sourceRootName;
|
||||
|
||||
@Schema(description = "对应分类/字典项ID")
|
||||
private String categoryRefId;
|
||||
|
||||
@Excel(name = "对应编码", width = 15)
|
||||
@Schema(description = "对应分类编码/字典项值")
|
||||
private String categoryRefCode;
|
||||
|
||||
@Excel(name = "对应分类", width = 20)
|
||||
@Schema(description = "对应分类名称冗余")
|
||||
private String categoryRefName;
|
||||
|
||||
@Excel(name = "优先级", width = 10)
|
||||
@Schema(description = "优先级(数字越小越优先)")
|
||||
private Integer priority;
|
||||
|
||||
@Schema(description = "租户ID")
|
||||
private Integer tenantId;
|
||||
|
||||
private String sysOrgCode;
|
||||
|
||||
@Excel(name = "创建人", width = 15)
|
||||
private String createBy;
|
||||
|
||||
@Excel(name = "创建时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
private String updateBy;
|
||||
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
|
||||
private Integer delFlag;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.jeecg.modules.xslmes.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslMixerMaterialKindCfg;
|
||||
|
||||
/**
|
||||
* MES 密炼物料种类配置
|
||||
*/
|
||||
public interface MesXslMixerMaterialKindCfgMapper extends BaseMapper<MesXslMixerMaterialKindCfg> {}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.jeecg.modules.xslmes.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import java.util.List;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslMixerMaterialKindCfg;
|
||||
|
||||
/**
|
||||
* MES 密炼物料种类配置
|
||||
*/
|
||||
public interface IMesXslMixerMaterialKindCfgService extends IService<MesXslMixerMaterialKindCfg> {
|
||||
|
||||
/**
|
||||
* 按根字典/分类展开明细行(未持久化)
|
||||
*/
|
||||
List<MesXslMixerMaterialKindCfg> expandLines(String sourceType, String sourceRootCode, Integer tenantId);
|
||||
|
||||
/**
|
||||
* 批量新增
|
||||
*/
|
||||
void saveBatchLines(List<MesXslMixerMaterialKindCfg> lines, Integer tenantId);
|
||||
|
||||
/**
|
||||
* 校验租户内种类键值/对应分类是否重复
|
||||
*/
|
||||
void checkDuplicate(MesXslMixerMaterialKindCfg line, String excludeId);
|
||||
}
|
||||
@@ -24,9 +24,11 @@ import org.jeecg.modules.mes.material.entity.MesMaterial;
|
||||
import org.jeecg.modules.mes.material.entity.MesMixerMaterial;
|
||||
import org.jeecg.modules.mes.material.service.IMesMaterialService;
|
||||
import org.jeecg.modules.mes.material.service.IMesMixerMaterialService;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.system.entity.SysCategory;
|
||||
import org.jeecg.modules.system.service.ISysCategoryService;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslEquipmentLedger;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpec;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecLine;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslMixerPsCompile;
|
||||
@@ -34,6 +36,7 @@ import org.jeecg.modules.xslmes.entity.MesXslMixingSpec;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslMixingSpecMaterial;
|
||||
import org.jeecg.modules.xslmes.mapper.MesXslFormulaSpecLineMapper;
|
||||
import org.jeecg.modules.xslmes.mapper.MesXslFormulaSpecMapper;
|
||||
import org.jeecg.modules.xslmes.service.IMesXslEquipmentLedgerService;
|
||||
import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecService;
|
||||
import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecSettingService;
|
||||
import org.jeecg.modules.xslmes.service.IMesXslMixingSpecService;
|
||||
@@ -44,16 +47,24 @@ import org.jeecg.modules.xslmes.vo.MesXslFormulaMixingGenerateRequestVO;
|
||||
import org.jeecg.modules.xslmes.vo.MesXslFormulaMixingGenerateRowVO;
|
||||
import org.jeecg.modules.system.entity.SysUser;
|
||||
import org.jeecg.modules.system.service.ISysUserService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecMapper, MesXslFormulaSpec>
|
||||
implements IMesXslFormulaSpecService {
|
||||
|
||||
private static final Set<String> RUBBER_CATEGORY_KEYS = Set.of("S", "P", "T", "C");
|
||||
private static final Pattern RUBBER_CODE_VERSION_PATTERN = Pattern.compile("([A-Z])01$");
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A48】生成混炼示方同步B/F段胶至密炼物料-----------
|
||||
private static final String CATEGORY_MASTER_MAJOR = "XSLMES_MATERIAL_MASTER";
|
||||
private static final String CATEGORY_MASTER_MINOR_A = "XSLMES_MATERIAL_MASTER_A";
|
||||
private static final String CATEGORY_FINAL_MAJOR = "XSLMES_MATERIAL_FINAL";
|
||||
private static final String CATEGORY_FINAL_MINOR_Q = "XSLMES_MATERIAL_FINAL_Q";
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A48】生成混炼示方同步B/F段胶至密炼物料-----------
|
||||
|
||||
@Resource
|
||||
private MesXslFormulaSpecLineMapper lineMapper;
|
||||
@@ -73,6 +84,9 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
|
||||
@Resource
|
||||
private IMesXslMixingSpecService mesXslMixingSpecService;
|
||||
|
||||
@Resource
|
||||
private IMesXslEquipmentLedgerService mesXslEquipmentLedgerService;
|
||||
|
||||
@Resource
|
||||
private ISysCategoryService sysCategoryService;
|
||||
|
||||
@@ -515,9 +529,17 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
|
||||
Map<String, MesMixerMaterial> mixerCache = new HashMap<>();
|
||||
Map<String, String> categoryNameCache = new HashMap<>();
|
||||
Map<String, Boolean> categoryRubberCache = new HashMap<>();
|
||||
Map<String, MesXslEquipmentLedger> equipmentCache = new HashMap<>();
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A44】F段终炼胶比重按配合示方整体PHR/体积汇总-----------
|
||||
BigDecimal compoundSpecificGravity = resolveCompoundSpecificGravity(formula, lines);
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A44】F段终炼胶比重按配合示方整体PHR/体积汇总-----------
|
||||
int created = 0;
|
||||
int totalStages = normalizeMixingStages(formula.getMixingStages());
|
||||
Date today = Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A48】生成混炼示方同步B/F段胶至密炼物料-----------
|
||||
Set<String> syncedRubberSpecCodes = new HashSet<>();
|
||||
Map<String, String> categoryIdCache = new HashMap<>();
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A48】生成混炼示方同步B/F段胶至密炼物料-----------
|
||||
for (MesXslFormulaMixingGenerateRowVO row : request.getRows()) {
|
||||
if (row == null || oConvertUtils.isEmpty(row.getSpecCode()) || row.getStageIndex() == null) {
|
||||
continue;
|
||||
@@ -525,6 +547,11 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
|
||||
if (CollectionUtils.isEmpty(row.getMachines())) {
|
||||
throw new IllegalArgumentException("示方「" + row.getSpecCode() + "」请至少选择一个机台");
|
||||
}
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A48】生成混炼示方同步B/F段胶至密炼物料-----------
|
||||
if (syncedRubberSpecCodes.add(row.getSpecCode().trim())) {
|
||||
syncGeneratedRubberMixerMaterial(row, formula, compoundSpecificGravity, categoryIdCache);
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A48】生成混炼示方同步B/F段胶至密炼物料-----------
|
||||
String materialStep = resolveMixingMaterialStep(row);
|
||||
int mixingColumn = resolveMixingColumn(row, formula);
|
||||
List<MesXslMixingSpecMaterial> materials = buildMixingMaterials(
|
||||
@@ -547,11 +574,25 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
|
||||
mixing.setStageCount(String.valueOf(row.getStageIndex()));
|
||||
}
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A40】生成时写入段数当前/总如2/3-----------
|
||||
if ("Q".equalsIgnoreCase(row.getStepType())) {
|
||||
mixing.setFinalRubberSg(formula.getQRubberSg());
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A44】生成混炼示方时按设备有效体积计算填充体积-----------
|
||||
mixing.setConvertFactor(BigDecimal.ONE);
|
||||
boolean isFinalStage = "Q".equalsIgnoreCase(row.getStepType());
|
||||
if (isFinalStage) {
|
||||
mixing.setFinalRubberSg(compoundSpecificGravity);
|
||||
} else {
|
||||
mixing.setMotherRubberSg(formula.getARubberSg());
|
||||
}
|
||||
BigDecimal specificGravity = isFinalStage ? compoundSpecificGravity : formula.getARubberSg();
|
||||
String machineLabel = StringUtils.defaultIfBlank(machine.getMachineName(), machine.getMachineId());
|
||||
MesXslEquipmentLedger equipment = equipmentCache.computeIfAbsent(
|
||||
machine.getMachineId(), mesXslEquipmentLedgerService::getById);
|
||||
if (equipment == null) {
|
||||
throw new IllegalArgumentException("机台「" + machineLabel + "」不存在或已删除,无法生成混炼示方");
|
||||
}
|
||||
BigDecimal effectiveVolume = parseEffectiveVolume(equipment.getEffectiveVolume(), machineLabel);
|
||||
BigDecimal totalWeight = sumMaterialUnitWeight(materials);
|
||||
mixing.setFillVolume(calcFillVolume(totalWeight, specificGravity, effectiveVolume, mixing.getConvertFactor()));
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A44】生成混炼示方时按设备有效体积计算填充体积-----------
|
||||
mesXslMixingSpecService.saveMain(mixing, materials, null, null, null);
|
||||
created++;
|
||||
}
|
||||
@@ -562,6 +603,214 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
|
||||
return created;
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A44】生成混炼示方时按设备有效体积计算填充体积-----------
|
||||
/** 配合示方整体比重(终炼胶比重)= TOTAL PHR ÷ 全部明细体积合计 */
|
||||
private BigDecimal resolveCompoundSpecificGravity(MesXslFormulaSpec formula, List<MesXslFormulaSpecLine> lines) {
|
||||
if (CollectionUtils.isEmpty(lines)) {
|
||||
return null;
|
||||
}
|
||||
BigDecimal totalPhr = formula != null && formula.getTotalPhr() != null && formula.getTotalPhr().compareTo(BigDecimal.ZERO) > 0
|
||||
? formula.getTotalPhr()
|
||||
: BigDecimal.ZERO;
|
||||
if (totalPhr.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
for (MesXslFormulaSpecLine line : lines) {
|
||||
if (line != null && line.getPhr() != null) {
|
||||
totalPhr = totalPhr.add(line.getPhr());
|
||||
}
|
||||
}
|
||||
}
|
||||
BigDecimal totalVolume = BigDecimal.ZERO;
|
||||
for (MesXslFormulaSpecLine line : lines) {
|
||||
BigDecimal volume = resolveLineVolume(line);
|
||||
if (volume != null) {
|
||||
totalVolume = totalVolume.add(volume);
|
||||
}
|
||||
}
|
||||
if (totalPhr.compareTo(BigDecimal.ZERO) <= 0 || totalVolume.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return null;
|
||||
}
|
||||
return totalPhr.divide(totalVolume, 6, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
/** 解析设备台账有效体积(支持纯数字或带单位的字符串) */
|
||||
private BigDecimal parseEffectiveVolume(String raw, String machineLabel) {
|
||||
if (StringUtils.isBlank(raw)) {
|
||||
throw new IllegalArgumentException("机台「" + machineLabel + "」未维护有效体积,无法计算填充体积");
|
||||
}
|
||||
String trimmed = raw.trim();
|
||||
try {
|
||||
BigDecimal value = new BigDecimal(trimmed);
|
||||
if (value.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
throw new IllegalArgumentException("机台「" + machineLabel + "」有效体积必须大于 0");
|
||||
}
|
||||
return value;
|
||||
} catch (NumberFormatException ignored) {
|
||||
Matcher matcher = Pattern.compile("([0-9]+(?:\\.[0-9]+)?)").matcher(trimmed);
|
||||
if (matcher.find()) {
|
||||
BigDecimal value = new BigDecimal(matcher.group(1));
|
||||
if (value.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
throw new IllegalArgumentException("机台「" + machineLabel + "」有效体积必须大于 0");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
throw new IllegalArgumentException("机台「" + machineLabel + "」有效体积格式无效:" + raw);
|
||||
}
|
||||
}
|
||||
|
||||
/** 橡胶及配合剂明细单重合计 */
|
||||
private BigDecimal sumMaterialUnitWeight(List<MesXslMixingSpecMaterial> materials) {
|
||||
if (CollectionUtils.isEmpty(materials)) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
BigDecimal total = BigDecimal.ZERO;
|
||||
for (MesXslMixingSpecMaterial material : materials) {
|
||||
if (material != null && material.getUnitWeight() != null) {
|
||||
total = total.add(material.getUnitWeight());
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充体积(%) = 本段单重合计 ÷ 本段比重 ÷ 机台有效体积(L) × 100 × 换算系数
|
||||
*/
|
||||
private BigDecimal calcFillVolume(
|
||||
BigDecimal totalWeight,
|
||||
BigDecimal specificGravity,
|
||||
BigDecimal effectiveVolume,
|
||||
BigDecimal convertFactor) {
|
||||
if (totalWeight == null || totalWeight.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
throw new IllegalArgumentException("本段橡胶及配合剂单重合计无效,无法计算填充体积");
|
||||
}
|
||||
if (specificGravity == null || specificGravity.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
throw new IllegalArgumentException("本段比重无效,无法计算填充体积");
|
||||
}
|
||||
if (effectiveVolume == null || effectiveVolume.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
throw new IllegalArgumentException("机台有效体积无效,无法计算填充体积");
|
||||
}
|
||||
BigDecimal factor = convertFactor == null || convertFactor.compareTo(BigDecimal.ZERO) <= 0
|
||||
? BigDecimal.ONE
|
||||
: convertFactor;
|
||||
BigDecimal materialVolume = totalWeight.divide(specificGravity, 6, RoundingMode.HALF_UP);
|
||||
return materialVolume
|
||||
.divide(effectiveVolume, 6, RoundingMode.HALF_UP)
|
||||
.multiply(BigDecimal.valueOf(100))
|
||||
.multiply(factor)
|
||||
.setScale(6, RoundingMode.HALF_UP);
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A44】生成混炼示方时按设备有效体积计算填充体积-----------
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A48】生成混炼示方同步B/F段胶至密炼物料-----------
|
||||
/**
|
||||
* 生成混炼示方时,将 B 段/F 段胶料同步写入密炼物料:
|
||||
* B 段 -> 物料大类「母炼胶」+ 小类「A胶」;F 段 -> 物料大类「终炼胶」+ 小类「Q胶」。
|
||||
*/
|
||||
private void syncGeneratedRubberMixerMaterial(
|
||||
MesXslFormulaMixingGenerateRowVO row,
|
||||
MesXslFormulaSpec formula,
|
||||
BigDecimal compoundSpecificGravity,
|
||||
Map<String, String> categoryIdCache) {
|
||||
if (row == null || StringUtils.isBlank(row.getSpecCode())) {
|
||||
return;
|
||||
}
|
||||
String specCode = row.getSpecCode().trim();
|
||||
boolean isFinalStage = "Q".equalsIgnoreCase(resolveMixingMaterialStep(row));
|
||||
String majorCode = isFinalStage ? CATEGORY_FINAL_MAJOR : CATEGORY_MASTER_MAJOR;
|
||||
String minorCode = isFinalStage ? CATEGORY_FINAL_MINOR_Q : CATEGORY_MASTER_MINOR_A;
|
||||
String majorCategoryId = resolveCategoryIdByCode(majorCode, categoryIdCache);
|
||||
String minorCategoryId = resolveCategoryIdByCode(minorCode, categoryIdCache);
|
||||
if (StringUtils.isBlank(majorCategoryId) || StringUtils.isBlank(minorCategoryId)) {
|
||||
throw new IllegalArgumentException(
|
||||
"未找到物料分类「" + (isFinalStage ? "终炼胶/Q胶" : "母炼胶/A胶") + "」,请先维护 MES 物料分类字典");
|
||||
}
|
||||
BigDecimal specificGravity = isFinalStage ? compoundSpecificGravity : formula.getARubberSg();
|
||||
String rubberName = resolveRubberName(formula);
|
||||
String materialDesc = StringUtils.isNotBlank(formula.getPurpose()) ? formula.getPurpose().trim() : rubberName;
|
||||
|
||||
MesMixerMaterial existing = findMixerMaterialByCodeOrName(specCode);
|
||||
Date now = new Date();
|
||||
if (existing != null) {
|
||||
existing.setMajorCategoryId(majorCategoryId);
|
||||
existing.setMinorCategoryId(minorCategoryId);
|
||||
existing.setSpecificGravity(specificGravity);
|
||||
if (StringUtils.isNotBlank(materialDesc)) {
|
||||
existing.setMaterialDesc(materialDesc);
|
||||
}
|
||||
if (StringUtils.isBlank(existing.getMaterialCode())) {
|
||||
existing.setMaterialCode(specCode);
|
||||
}
|
||||
if (StringUtils.isBlank(existing.getMaterialName())) {
|
||||
existing.setMaterialName(specCode);
|
||||
}
|
||||
existing.setUseStatus(existing.getUseStatus() == null ? 1 : existing.getUseStatus());
|
||||
existing.setUpdateTime(now);
|
||||
mesMixerMaterialService.updateById(existing);
|
||||
log.info(
|
||||
"[混炼示方生成] 更新密炼物料 id={}, code={}, major={}, minor={}, sg={}",
|
||||
existing.getId(),
|
||||
specCode,
|
||||
majorCode,
|
||||
minorCode,
|
||||
specificGravity);
|
||||
return;
|
||||
}
|
||||
|
||||
MesMixerMaterial material = new MesMixerMaterial();
|
||||
material.setMaterialCode(specCode);
|
||||
material.setMaterialName(specCode);
|
||||
material.setMaterialDesc(materialDesc);
|
||||
material.setAliasName(StringUtils.isNotBlank(rubberName) ? rubberName : null);
|
||||
material.setMajorCategoryId(majorCategoryId);
|
||||
material.setMinorCategoryId(minorCategoryId);
|
||||
material.setSpecificGravity(specificGravity);
|
||||
material.setFeedManageStatus(0);
|
||||
material.setUseStatus(1);
|
||||
material.setDelFlag(CommonConstant.DEL_FLAG_0);
|
||||
material.setCreateTime(now);
|
||||
material.setUpdateTime(now);
|
||||
mesMixerMaterialService.save(material);
|
||||
log.info(
|
||||
"[混炼示方生成] 新增密炼物料 id={}, code={}, major={}, minor={}, sg={}",
|
||||
material.getId(),
|
||||
specCode,
|
||||
majorCode,
|
||||
minorCode,
|
||||
specificGravity);
|
||||
}
|
||||
|
||||
private MesMixerMaterial findMixerMaterialByCodeOrName(String specCode) {
|
||||
MesMixerMaterial byCode = mesMixerMaterialService.getOne(
|
||||
new LambdaQueryWrapper<MesMixerMaterial>()
|
||||
.eq(MesMixerMaterial::getMaterialCode, specCode)
|
||||
.and(w -> w.eq(MesMixerMaterial::getDelFlag, CommonConstant.DEL_FLAG_0).or().isNull(MesMixerMaterial::getDelFlag))
|
||||
.last("limit 1"));
|
||||
if (byCode != null) {
|
||||
return byCode;
|
||||
}
|
||||
return mesMixerMaterialService.getOne(
|
||||
new LambdaQueryWrapper<MesMixerMaterial>()
|
||||
.eq(MesMixerMaterial::getMaterialName, specCode)
|
||||
.and(w -> w.eq(MesMixerMaterial::getDelFlag, CommonConstant.DEL_FLAG_0).or().isNull(MesMixerMaterial::getDelFlag))
|
||||
.last("limit 1"));
|
||||
}
|
||||
|
||||
private String resolveCategoryIdByCode(String categoryCode, Map<String, String> cache) {
|
||||
if (StringUtils.isBlank(categoryCode)) {
|
||||
return null;
|
||||
}
|
||||
if (cache != null && cache.containsKey(categoryCode)) {
|
||||
return cache.get(categoryCode);
|
||||
}
|
||||
SysCategory category = sysCategoryService.getOne(
|
||||
new LambdaQueryWrapper<SysCategory>().eq(SysCategory::getCode, categoryCode.trim()).last("limit 1"));
|
||||
String categoryId = category != null ? category.getId() : null;
|
||||
if (cache != null) {
|
||||
cache.put(categoryCode, categoryId);
|
||||
}
|
||||
return categoryId;
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A48】生成混炼示方同步B/F段胶至密炼物料-----------
|
||||
|
||||
private int normalizeMixingStages(Integer mixingStages) {
|
||||
if (mixingStages == null || mixingStages <= 0) {
|
||||
return 0;
|
||||
@@ -861,7 +1110,7 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
|
||||
material.setMixerMaterialDesc(
|
||||
StringUtils.isNotBlank(line.getMaterialDesc()) ? line.getMaterialDesc() : line.getMixerMaterialName());
|
||||
material.setUnitWeight(unitWeight);
|
||||
fillMaterialCategory(material, line.getMixerMaterialId(), mixerCache, categoryNameCache, categoryRubberCache);
|
||||
fillMaterialCategory(material, line.getMixerMaterialId(), line, mixerCache, categoryNameCache, categoryRubberCache);
|
||||
return material;
|
||||
}
|
||||
|
||||
@@ -884,6 +1133,7 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
|
||||
private void fillMaterialCategory(
|
||||
MesXslMixingSpecMaterial material,
|
||||
String mixerMaterialId,
|
||||
MesXslFormulaSpecLine line,
|
||||
Map<String, MesMixerMaterial> mixerCache,
|
||||
Map<String, String> categoryNameCache,
|
||||
Map<String, Boolean> categoryRubberCache) {
|
||||
@@ -894,18 +1144,27 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
|
||||
if (mixer == null) {
|
||||
return;
|
||||
}
|
||||
String weighMode = line != null ? line.getWeighMode() : null;
|
||||
String majorName = resolveCategoryName(mixer.getMajorCategoryId(), categoryNameCache);
|
||||
String minorName = resolveCategoryName(mixer.getMinorCategoryId(), categoryNameCache);
|
||||
material.setMaterialMajor(majorName);
|
||||
material.setMaterialMinor(minorName);
|
||||
material.setMaterialKind(resolveMixingMaterialKind(mixer.getMinorCategoryId(), minorName, categoryRubberCache));
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】生成混炼示方时称量方式优先映射种类-----------
|
||||
material.setMaterialKind(
|
||||
resolveMixingMaterialKind(weighMode, mixer.getMinorCategoryId(), minorName, categoryRubberCache));
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】生成混炼示方时称量方式优先映射种类-----------
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】生成混炼示方时称量方式优先映射种类-----------
|
||||
/**
|
||||
* 种类:物料小类在分类字典勾选「胶料」则显示「胶料」,否则显示小类分类名称。
|
||||
* 种类:配合示方称量方式优先;否则物料小类勾选「胶料」则显示「胶料」,否则显示小类名称。
|
||||
*/
|
||||
private String resolveMixingMaterialKind(
|
||||
String minorCategoryId, String minorCategoryName, Map<String, Boolean> categoryRubberCache) {
|
||||
String weighMode, String minorCategoryId, String minorCategoryName, Map<String, Boolean> categoryRubberCache) {
|
||||
String weighKind = resolveWeighModeMaterialKind(weighMode);
|
||||
if (StringUtils.isNotBlank(weighKind)) {
|
||||
return weighKind;
|
||||
}
|
||||
if (isCategoryRubber(minorCategoryId, categoryRubberCache)) {
|
||||
return "胶料";
|
||||
}
|
||||
@@ -915,6 +1174,23 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
|
||||
return null;
|
||||
}
|
||||
|
||||
/** 配合示方自动/人工称量 -> 混炼示方种类 */
|
||||
private String resolveWeighModeMaterialKind(String weighMode) {
|
||||
if (StringUtils.isBlank(weighMode)) {
|
||||
return null;
|
||||
}
|
||||
String normalized = weighMode.trim();
|
||||
String lower = normalized.toLowerCase();
|
||||
if (lower.startsWith("auto") || normalized.contains("自动")) {
|
||||
return "自动";
|
||||
}
|
||||
if ("manual".equals(lower) || normalized.contains("人工")) {
|
||||
return "人工";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】生成混炼示方时称量方式优先映射种类-----------
|
||||
|
||||
private boolean isCategoryRubber(String categoryId, Map<String, Boolean> cache) {
|
||||
if (oConvertUtils.isEmpty(categoryId)) {
|
||||
return false;
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
package org.jeecg.modules.xslmes.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.common.util.TokenUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.common.config.TenantContext;
|
||||
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
||||
import org.jeecg.modules.system.entity.SysCategory;
|
||||
import org.jeecg.modules.system.entity.SysDict;
|
||||
import org.jeecg.modules.system.entity.SysDictItem;
|
||||
import org.jeecg.modules.system.service.ISysCategoryService;
|
||||
import org.jeecg.modules.system.service.ISysDictItemService;
|
||||
import org.jeecg.modules.system.service.ISysDictService;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslMixerMaterialKindCfg;
|
||||
import org.jeecg.modules.xslmes.mapper.MesXslMixerMaterialKindCfgMapper;
|
||||
import org.jeecg.modules.xslmes.service.IMesXslMixerMaterialKindCfgService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* MES 密炼物料种类配置
|
||||
*/
|
||||
@Service
|
||||
public class MesXslMixerMaterialKindCfgServiceImpl
|
||||
extends ServiceImpl<MesXslMixerMaterialKindCfgMapper, MesXslMixerMaterialKindCfg>
|
||||
implements IMesXslMixerMaterialKindCfgService {
|
||||
|
||||
@Autowired
|
||||
private ISysDictService sysDictService;
|
||||
|
||||
@Autowired
|
||||
private ISysDictItemService sysDictItemService;
|
||||
|
||||
@Autowired
|
||||
private ISysCategoryService sysCategoryService;
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A51】密炼物料种类配置展开与批量保存-----------
|
||||
@Override
|
||||
public List<MesXslMixerMaterialKindCfg> expandLines(String sourceType, String sourceRootCode, Integer tenantId) {
|
||||
if (oConvertUtils.isEmpty(sourceType) || oConvertUtils.isEmpty(sourceRootCode)) {
|
||||
throw new JeecgBootException("请选择数据源类型与根字典/分类");
|
||||
}
|
||||
String normalizedType = sourceType.trim().toLowerCase();
|
||||
String rootCode = sourceRootCode.trim();
|
||||
if (MesXslMixerMaterialKindCfg.SOURCE_TYPE_DICT.equals(normalizedType)) {
|
||||
return expandFromDict(rootCode, tenantId);
|
||||
}
|
||||
if (MesXslMixerMaterialKindCfg.SOURCE_TYPE_CATEGORY.equals(normalizedType)) {
|
||||
return expandFromCategory(rootCode, tenantId);
|
||||
}
|
||||
throw new JeecgBootException("不支持的数据源类型:" + sourceType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveBatchLines(List<MesXslMixerMaterialKindCfg> lines, Integer tenantId) {
|
||||
if (lines == null || lines.isEmpty()) {
|
||||
throw new JeecgBootException("请至少维护一条种类配置明细");
|
||||
}
|
||||
Integer resolvedTenantId = resolveTenantId(tenantId);
|
||||
Set<String> kindKeys = new HashSet<>();
|
||||
Set<String> categoryRefIds = new HashSet<>();
|
||||
for (MesXslMixerMaterialKindCfg line : lines) {
|
||||
String err = validateLine(line, kindKeys, categoryRefIds);
|
||||
if (err != null) {
|
||||
throw new JeecgBootException(err);
|
||||
}
|
||||
line.setTenantId(resolvedTenantId);
|
||||
line.setDelFlag(CommonConstant.DEL_FLAG_0);
|
||||
checkDuplicate(line, null);
|
||||
}
|
||||
saveBatch(lines);
|
||||
}
|
||||
|
||||
private List<MesXslMixerMaterialKindCfg> expandFromDict(String dictCode, Integer tenantId) {
|
||||
LambdaQueryWrapper<SysDict> dictQw = new LambdaQueryWrapper<>();
|
||||
dictQw.eq(SysDict::getDictCode, dictCode);
|
||||
SysDict dict = sysDictService.getOne(dictQw, false);
|
||||
if (dict == null) {
|
||||
throw new JeecgBootException("数据字典不存在:" + dictCode);
|
||||
}
|
||||
LambdaQueryWrapper<SysDictItem> itemQw = new LambdaQueryWrapper<>();
|
||||
itemQw.eq(SysDictItem::getDictId, dict.getId());
|
||||
itemQw.eq(SysDictItem::getStatus, 1);
|
||||
itemQw.orderByAsc(SysDictItem::getSortOrder).orderByAsc(SysDictItem::getItemValue);
|
||||
List<SysDictItem> items = sysDictItemService.list(itemQw);
|
||||
if (items == null || items.isEmpty()) {
|
||||
throw new JeecgBootException("该数据字典下没有可用的字典项");
|
||||
}
|
||||
Set<String> existsRefIds = loadExistingCategoryRefIds(MesXslMixerMaterialKindCfg.SOURCE_TYPE_DICT, dictCode, tenantId);
|
||||
List<MesXslMixerMaterialKindCfg> result = new ArrayList<>();
|
||||
int priorityBase = 10;
|
||||
int index = 0;
|
||||
for (SysDictItem item : items) {
|
||||
if (item == null || oConvertUtils.isEmpty(item.getId())) {
|
||||
continue;
|
||||
}
|
||||
if (existsRefIds.contains(item.getId())) {
|
||||
continue;
|
||||
}
|
||||
MesXslMixerMaterialKindCfg cfg = new MesXslMixerMaterialKindCfg();
|
||||
cfg.setSourceType(MesXslMixerMaterialKindCfg.SOURCE_TYPE_DICT);
|
||||
cfg.setSourceRootCode(dictCode);
|
||||
cfg.setSourceRootName(dict.getDictName());
|
||||
cfg.setCategoryRefId(item.getId());
|
||||
cfg.setCategoryRefCode(item.getItemValue());
|
||||
cfg.setCategoryRefName(item.getItemText());
|
||||
cfg.setKindKey(item.getItemValue());
|
||||
cfg.setKindName(item.getItemText());
|
||||
cfg.setPriority(item.getSortOrder() != null ? item.getSortOrder() : priorityBase + index * 10);
|
||||
cfg.setTenantId(resolveTenantId(tenantId));
|
||||
result.add(cfg);
|
||||
index++;
|
||||
}
|
||||
if (result.isEmpty()) {
|
||||
throw new JeecgBootException("该数据字典下的字典项均已配置,无需重复带出");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<MesXslMixerMaterialKindCfg> expandFromCategory(String rootCode, Integer tenantId) {
|
||||
LambdaQueryWrapper<SysCategory> rootQw = new LambdaQueryWrapper<>();
|
||||
rootQw.eq(SysCategory::getCode, rootCode);
|
||||
SysCategory root = sysCategoryService.getOne(rootQw, false);
|
||||
if (root == null) {
|
||||
throw new JeecgBootException("分类字典不存在:" + rootCode);
|
||||
}
|
||||
List<SysCategory> descendants = new ArrayList<>();
|
||||
Deque<String> queue = new ArrayDeque<>();
|
||||
queue.add(root.getId());
|
||||
while (!queue.isEmpty()) {
|
||||
String parentId = queue.poll();
|
||||
LambdaQueryWrapper<SysCategory> childQw = new LambdaQueryWrapper<>();
|
||||
childQw.eq(SysCategory::getPid, parentId);
|
||||
childQw.orderByAsc(SysCategory::getCode);
|
||||
List<SysCategory> children = sysCategoryService.list(childQw);
|
||||
if (children == null || children.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
for (SysCategory child : children) {
|
||||
descendants.add(child);
|
||||
queue.add(child.getId());
|
||||
}
|
||||
}
|
||||
if (descendants.isEmpty()) {
|
||||
throw new JeecgBootException("该分类下没有可用的子分类");
|
||||
}
|
||||
Set<String> existsRefIds = loadExistingCategoryRefIds(MesXslMixerMaterialKindCfg.SOURCE_TYPE_CATEGORY, rootCode, tenantId);
|
||||
List<MesXslMixerMaterialKindCfg> result = new ArrayList<>();
|
||||
int priorityBase = 10;
|
||||
for (int i = 0; i < descendants.size(); i++) {
|
||||
SysCategory category = descendants.get(i);
|
||||
if (category == null || oConvertUtils.isEmpty(category.getId())) {
|
||||
continue;
|
||||
}
|
||||
if (existsRefIds.contains(category.getId())) {
|
||||
continue;
|
||||
}
|
||||
String refCode = oConvertUtils.isNotEmpty(category.getCode()) ? category.getCode() : category.getId();
|
||||
MesXslMixerMaterialKindCfg cfg = new MesXslMixerMaterialKindCfg();
|
||||
cfg.setSourceType(MesXslMixerMaterialKindCfg.SOURCE_TYPE_CATEGORY);
|
||||
cfg.setSourceRootCode(rootCode);
|
||||
cfg.setSourceRootName(root.getName());
|
||||
cfg.setCategoryRefId(category.getId());
|
||||
cfg.setCategoryRefCode(refCode);
|
||||
cfg.setCategoryRefName(category.getName());
|
||||
cfg.setKindKey(refCode);
|
||||
cfg.setKindName(category.getName());
|
||||
cfg.setPriority(priorityBase + i * 10);
|
||||
cfg.setTenantId(resolveTenantId(tenantId));
|
||||
result.add(cfg);
|
||||
}
|
||||
if (result.isEmpty()) {
|
||||
throw new JeecgBootException("该分类下的子分类均已配置,无需重复带出");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Set<String> loadExistingCategoryRefIds(String sourceType, String sourceRootCode, Integer tenantId) {
|
||||
LambdaQueryWrapper<MesXslMixerMaterialKindCfg> qw = new LambdaQueryWrapper<>();
|
||||
qw.eq(MesXslMixerMaterialKindCfg::getSourceType, sourceType);
|
||||
qw.eq(MesXslMixerMaterialKindCfg::getSourceRootCode, sourceRootCode);
|
||||
qw.and(q -> q.eq(MesXslMixerMaterialKindCfg::getDelFlag, CommonConstant.DEL_FLAG_0).or().isNull(MesXslMixerMaterialKindCfg::getDelFlag));
|
||||
Integer resolvedTenantId = resolveTenantId(tenantId);
|
||||
if (resolvedTenantId != null && MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
|
||||
qw.eq(MesXslMixerMaterialKindCfg::getTenantId, resolvedTenantId);
|
||||
}
|
||||
qw.select(MesXslMixerMaterialKindCfg::getCategoryRefId);
|
||||
List<MesXslMixerMaterialKindCfg> exists = list(qw);
|
||||
Set<String> ids = new HashSet<>();
|
||||
if (exists != null) {
|
||||
for (MesXslMixerMaterialKindCfg row : exists) {
|
||||
if (row != null && oConvertUtils.isNotEmpty(row.getCategoryRefId())) {
|
||||
ids.add(row.getCategoryRefId());
|
||||
}
|
||||
}
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
private String validateLine(MesXslMixerMaterialKindCfg line, Set<String> kindKeys, Set<String> categoryRefIds) {
|
||||
if (line == null) {
|
||||
return "存在空的明细行";
|
||||
}
|
||||
if (oConvertUtils.isEmpty(line.getKindKey())) {
|
||||
return "种类键值不能为空";
|
||||
}
|
||||
if (oConvertUtils.isEmpty(line.getKindName())) {
|
||||
return "种类名称不能为空";
|
||||
}
|
||||
if (oConvertUtils.isEmpty(line.getSourceType())) {
|
||||
return "数据源类型不能为空";
|
||||
}
|
||||
if (oConvertUtils.isEmpty(line.getCategoryRefId())) {
|
||||
return "对应分类不能为空";
|
||||
}
|
||||
String kindKey = line.getKindKey().trim();
|
||||
if (!kindKeys.add(kindKey)) {
|
||||
return "本次提交存在重复的种类键值:" + kindKey;
|
||||
}
|
||||
String refId = line.getCategoryRefId().trim();
|
||||
if (!categoryRefIds.add(refId)) {
|
||||
return "本次提交存在重复的对应分类";
|
||||
}
|
||||
if (line.getPriority() == null) {
|
||||
line.setPriority(999);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkDuplicate(MesXslMixerMaterialKindCfg line, String excludeId) {
|
||||
Integer tenantId = resolveTenantId(line.getTenantId());
|
||||
LambdaQueryWrapper<MesXslMixerMaterialKindCfg> kindQw = new LambdaQueryWrapper<>();
|
||||
kindQw.eq(MesXslMixerMaterialKindCfg::getKindKey, line.getKindKey().trim());
|
||||
kindQw.and(q -> q.eq(MesXslMixerMaterialKindCfg::getDelFlag, CommonConstant.DEL_FLAG_0).or().isNull(MesXslMixerMaterialKindCfg::getDelFlag));
|
||||
if (tenantId != null && MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
|
||||
kindQw.eq(MesXslMixerMaterialKindCfg::getTenantId, tenantId);
|
||||
}
|
||||
if (oConvertUtils.isNotEmpty(excludeId)) {
|
||||
kindQw.ne(MesXslMixerMaterialKindCfg::getId, excludeId);
|
||||
}
|
||||
if (count(kindQw) > 0) {
|
||||
throw new JeecgBootException("种类键值已存在:" + line.getKindKey());
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<MesXslMixerMaterialKindCfg> refQw = new LambdaQueryWrapper<>();
|
||||
refQw.eq(MesXslMixerMaterialKindCfg::getCategoryRefId, line.getCategoryRefId().trim());
|
||||
refQw.and(q -> q.eq(MesXslMixerMaterialKindCfg::getDelFlag, CommonConstant.DEL_FLAG_0).or().isNull(MesXslMixerMaterialKindCfg::getDelFlag));
|
||||
if (tenantId != null && MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
|
||||
refQw.eq(MesXslMixerMaterialKindCfg::getTenantId, tenantId);
|
||||
}
|
||||
if (oConvertUtils.isNotEmpty(excludeId)) {
|
||||
refQw.ne(MesXslMixerMaterialKindCfg::getId, excludeId);
|
||||
}
|
||||
if (count(refQw) > 0) {
|
||||
throw new JeecgBootException("对应分类已配置:" + line.getCategoryRefName());
|
||||
}
|
||||
}
|
||||
|
||||
private static Integer resolveTenantId(Integer tenantId) {
|
||||
if (tenantId != null) {
|
||||
return tenantId;
|
||||
}
|
||||
String ts = TenantContext.getTenant();
|
||||
if (oConvertUtils.isEmpty(ts)) {
|
||||
try {
|
||||
HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
|
||||
if (request != null) {
|
||||
ts = TokenUtils.getTenantIdByRequest(request);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
if (oConvertUtils.isEmpty(ts)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(ts);
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A51】密炼物料种类配置展开与批量保存-----------
|
||||
}
|
||||
@@ -2,14 +2,24 @@ package org.jeecg.modules.xslmes.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.Db;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.modules.mes.material.entity.MesMixerMaterial;
|
||||
import org.jeecg.modules.mes.material.service.IMesMixerMaterialService;
|
||||
import org.jeecg.modules.system.entity.SysCategory;
|
||||
import org.jeecg.modules.system.service.ISysCategoryService;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslMixingSpec;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslMixingSpecDownStep;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslMixingSpecMaterial;
|
||||
@@ -27,11 +37,19 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMapper, MesXslMixingSpec>
|
||||
implements IMesXslMixingSpecService {
|
||||
|
||||
private static final String TCU_UP = "up_mixer";
|
||||
private static final String TCU_DOWN = "down_mixer";
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A49】删除混炼示方时同步删除B/F段胶密炼物料-----------
|
||||
private static final String CATEGORY_MASTER_MAJOR = "XSLMES_MATERIAL_MASTER";
|
||||
private static final String CATEGORY_MASTER_MINOR_A = "XSLMES_MATERIAL_MASTER_A";
|
||||
private static final String CATEGORY_FINAL_MAJOR = "XSLMES_MATERIAL_FINAL";
|
||||
private static final String CATEGORY_FINAL_MINOR_Q = "XSLMES_MATERIAL_FINAL_Q";
|
||||
private static final Pattern GENERATED_B_RUBBER_SPEC_PATTERN = Pattern.compile("^B\\d", Pattern.CASE_INSENSITIVE);
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A49】删除混炼示方时同步删除B/F段胶密炼物料-----------
|
||||
|
||||
@Resource
|
||||
private MesXslMixingSpecMaterialMapper materialMapper;
|
||||
@@ -42,6 +60,12 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
|
||||
@Resource
|
||||
private MesXslMixingSpecTcuMapper tcuMapper;
|
||||
|
||||
@Resource
|
||||
private IMesMixerMaterialService mesMixerMaterialService;
|
||||
|
||||
@Resource
|
||||
private ISysCategoryService sysCategoryService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveMain(
|
||||
@@ -50,10 +74,17 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
|
||||
List<MesXslMixingSpecStep> stepList,
|
||||
List<MesXslMixingSpecDownStep> downStepList,
|
||||
List<MesXslMixingSpecTcu> tcuList) {
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
||||
SavePerfTrace trace = new SavePerfTrace("新增", main);
|
||||
trace.logPayloadSize(materialList, stepList, downStepList, tcuList);
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】混炼示方主子表新增保存-----------
|
||||
normalizeMain(main);
|
||||
trace.step("normalizeMain");
|
||||
this.save(main);
|
||||
saveChildren(main.getId(), materialList, stepList, downStepList, tcuList);
|
||||
trace.step("saveMain", "mainId", main.getId());
|
||||
saveChildren(main.getId(), materialList, stepList, downStepList, tcuList, trace);
|
||||
trace.finish();
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】混炼示方主子表新增保存-----------
|
||||
}
|
||||
|
||||
@@ -65,19 +96,32 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
|
||||
List<MesXslMixingSpecStep> stepList,
|
||||
List<MesXslMixingSpecDownStep> downStepList,
|
||||
List<MesXslMixingSpecTcu> tcuList) {
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
||||
SavePerfTrace trace = new SavePerfTrace("编辑", main);
|
||||
trace.logPayloadSize(materialList, stepList, downStepList, tcuList);
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】混炼示方主子表编辑保存-----------
|
||||
normalizeMain(main);
|
||||
trace.step("normalizeMain");
|
||||
this.updateById(main);
|
||||
clearChildren(main.getId());
|
||||
saveChildren(main.getId(), materialList, stepList, downStepList, tcuList);
|
||||
trace.step("updateMain");
|
||||
clearChildren(main.getId(), trace);
|
||||
saveChildren(main.getId(), materialList, stepList, downStepList, tcuList, trace);
|
||||
trace.finish();
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】混炼示方主子表编辑保存-----------
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delMain(String id) {
|
||||
MesXslMixingSpec main = this.getById(id);
|
||||
clearChildren(id);
|
||||
this.removeById(id);
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A49】删除混炼示方时同步删除B/F段胶密炼物料-----------
|
||||
if (main != null) {
|
||||
syncDeleteGeneratedRubberMixerMaterial(main.getSpecName());
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A49】删除混炼示方时同步删除B/F段胶密炼物料-----------
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -203,10 +247,26 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
|
||||
}
|
||||
|
||||
private void clearChildren(String mainId) {
|
||||
clearChildren(mainId, null);
|
||||
}
|
||||
|
||||
private void clearChildren(String mainId, SavePerfTrace trace) {
|
||||
materialMapper.delete(new LambdaQueryWrapper<MesXslMixingSpecMaterial>().eq(MesXslMixingSpecMaterial::getMixingSpecId, mainId));
|
||||
if (trace != null) {
|
||||
trace.step("deleteMaterialChildren");
|
||||
}
|
||||
stepMapper.delete(new LambdaQueryWrapper<MesXslMixingSpecStep>().eq(MesXslMixingSpecStep::getMixingSpecId, mainId));
|
||||
if (trace != null) {
|
||||
trace.step("deleteStepChildren");
|
||||
}
|
||||
downStepMapper.delete(new LambdaQueryWrapper<MesXslMixingSpecDownStep>().eq(MesXslMixingSpecDownStep::getMixingSpecId, mainId));
|
||||
if (trace != null) {
|
||||
trace.step("deleteDownStepChildren");
|
||||
}
|
||||
tcuMapper.delete(new LambdaQueryWrapper<MesXslMixingSpecTcu>().eq(MesXslMixingSpecTcu::getMixingSpecId, mainId));
|
||||
if (trace != null) {
|
||||
trace.step("deleteTcuChildren");
|
||||
}
|
||||
}
|
||||
|
||||
private void saveChildren(
|
||||
@@ -215,54 +275,142 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
|
||||
List<MesXslMixingSpecStep> stepList,
|
||||
List<MesXslMixingSpecDownStep> downStepList,
|
||||
List<MesXslMixingSpecTcu> tcuList) {
|
||||
saveChildren(mainId, materialList, stepList, downStepList, tcuList, null);
|
||||
}
|
||||
|
||||
private void saveChildren(
|
||||
String mainId,
|
||||
List<MesXslMixingSpecMaterial> materialList,
|
||||
List<MesXslMixingSpecStep> stepList,
|
||||
List<MesXslMixingSpecDownStep> downStepList,
|
||||
List<MesXslMixingSpecTcu> tcuList,
|
||||
SavePerfTrace trace) {
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A45】混炼示方子表批量插入避免保存超时-----------
|
||||
Date now = new Date();
|
||||
saveMaterialChildren(mainId, materialList, now, trace);
|
||||
saveStepChildren(mainId, stepList, now, trace);
|
||||
saveDownStepChildren(mainId, downStepList, now, trace);
|
||||
saveTcuChildren(mainId, tcuList, now, trace);
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A45】混炼示方子表批量插入避免保存超时-----------
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A45】混炼示方子表批量插入避免保存超时-----------
|
||||
private void saveMaterialChildren(String mainId, List<MesXslMixingSpecMaterial> materialList, Date now) {
|
||||
saveMaterialChildren(mainId, materialList, now, null);
|
||||
}
|
||||
|
||||
private void saveMaterialChildren(String mainId, List<MesXslMixingSpecMaterial> materialList, Date now, SavePerfTrace trace) {
|
||||
if (CollectionUtils.isEmpty(materialList)) {
|
||||
return;
|
||||
}
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A41】橡胶及配合剂明细累计按种类分组合计-----------
|
||||
fillMaterialAccumWeight(materialList);
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A41】橡胶及配合剂明细累计按种类分组合计-----------
|
||||
if (trace != null) {
|
||||
trace.step("fillMaterialAccumWeight", "rows", countRows(materialList));
|
||||
}
|
||||
List<MesXslMixingSpecMaterial> rows = new ArrayList<>();
|
||||
int sort = 0;
|
||||
if (!CollectionUtils.isEmpty(materialList)) {
|
||||
for (MesXslMixingSpecMaterial row : materialList) {
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
row.setId(null);
|
||||
row.setMixingSpecId(mainId);
|
||||
row.setSortNo(sort++);
|
||||
if (row.getCreateTime() == null) {
|
||||
row.setCreateTime(now);
|
||||
}
|
||||
materialMapper.insert(row);
|
||||
for (MesXslMixingSpecMaterial row : materialList) {
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
row.setId(null);
|
||||
row.setMixingSpecId(mainId);
|
||||
row.setSortNo(sort++);
|
||||
if (row.getCreateTime() == null) {
|
||||
row.setCreateTime(now);
|
||||
}
|
||||
rows.add(row);
|
||||
}
|
||||
if (trace != null) {
|
||||
trace.step("buildMaterialRows", "rows", rows.size());
|
||||
}
|
||||
if (!rows.isEmpty()) {
|
||||
Db.saveBatch(rows);
|
||||
if (trace != null) {
|
||||
trace.step("batchInsertMaterial", "rows", rows.size());
|
||||
}
|
||||
}
|
||||
sort = 0;
|
||||
if (!CollectionUtils.isEmpty(stepList)) {
|
||||
for (MesXslMixingSpecStep row : stepList) {
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
row.setId(null);
|
||||
row.setMixingSpecId(mainId);
|
||||
row.setSortNo(sort++);
|
||||
if (row.getCreateTime() == null) {
|
||||
row.setCreateTime(now);
|
||||
}
|
||||
stepMapper.insert(row);
|
||||
}
|
||||
|
||||
private void saveStepChildren(String mainId, List<MesXslMixingSpecStep> stepList, Date now) {
|
||||
saveStepChildren(mainId, stepList, now, null);
|
||||
}
|
||||
|
||||
private void saveStepChildren(String mainId, List<MesXslMixingSpecStep> stepList, Date now, SavePerfTrace trace) {
|
||||
if (CollectionUtils.isEmpty(stepList)) {
|
||||
return;
|
||||
}
|
||||
List<MesXslMixingSpecStep> rows = new ArrayList<>();
|
||||
int sort = 0;
|
||||
for (MesXslMixingSpecStep row : stepList) {
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
row.setId(null);
|
||||
row.setMixingSpecId(mainId);
|
||||
row.setSortNo(sort++);
|
||||
if (row.getCreateTime() == null) {
|
||||
row.setCreateTime(now);
|
||||
}
|
||||
rows.add(row);
|
||||
}
|
||||
if (trace != null) {
|
||||
trace.step("buildStepRows", "rows", rows.size());
|
||||
}
|
||||
if (!rows.isEmpty()) {
|
||||
Db.saveBatch(rows);
|
||||
if (trace != null) {
|
||||
trace.step("batchInsertStep", "rows", rows.size());
|
||||
}
|
||||
}
|
||||
sort = 0;
|
||||
if (!CollectionUtils.isEmpty(downStepList)) {
|
||||
for (MesXslMixingSpecDownStep row : downStepList) {
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
row.setId(null);
|
||||
row.setMixingSpecId(mainId);
|
||||
row.setSortNo(sort++);
|
||||
if (row.getCreateTime() == null) {
|
||||
row.setCreateTime(now);
|
||||
}
|
||||
downStepMapper.insert(row);
|
||||
}
|
||||
|
||||
private void saveDownStepChildren(String mainId, List<MesXslMixingSpecDownStep> downStepList, Date now) {
|
||||
saveDownStepChildren(mainId, downStepList, now, null);
|
||||
}
|
||||
|
||||
private void saveDownStepChildren(String mainId, List<MesXslMixingSpecDownStep> downStepList, Date now, SavePerfTrace trace) {
|
||||
if (CollectionUtils.isEmpty(downStepList)) {
|
||||
return;
|
||||
}
|
||||
List<MesXslMixingSpecDownStep> rows = new ArrayList<>();
|
||||
int sort = 0;
|
||||
for (MesXslMixingSpecDownStep row : downStepList) {
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
row.setId(null);
|
||||
row.setMixingSpecId(mainId);
|
||||
row.setSortNo(sort++);
|
||||
if (row.getCreateTime() == null) {
|
||||
row.setCreateTime(now);
|
||||
}
|
||||
rows.add(row);
|
||||
}
|
||||
if (trace != null) {
|
||||
trace.step("buildDownStepRows", "rows", rows.size());
|
||||
}
|
||||
if (!rows.isEmpty()) {
|
||||
Db.saveBatch(rows);
|
||||
if (trace != null) {
|
||||
trace.step("batchInsertDownStep", "rows", rows.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void saveTcuChildren(String mainId, List<MesXslMixingSpecTcu> tcuList, Date now) {
|
||||
saveTcuChildren(mainId, tcuList, now, null);
|
||||
}
|
||||
|
||||
private void saveTcuChildren(String mainId, List<MesXslMixingSpecTcu> tcuList, Date now, SavePerfTrace trace) {
|
||||
List<MesXslMixingSpecTcu> tcuRows = fillDefaultTcuRows(tcuList);
|
||||
sort = 0;
|
||||
if (trace != null) {
|
||||
trace.step("fillDefaultTcuRows", "rows", tcuRows.size());
|
||||
}
|
||||
List<MesXslMixingSpecTcu> rows = new ArrayList<>();
|
||||
int sort = 0;
|
||||
for (MesXslMixingSpecTcu row : tcuRows) {
|
||||
row.setId(null);
|
||||
row.setMixingSpecId(mainId);
|
||||
@@ -273,9 +421,139 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
|
||||
if (TCU_DOWN.equals(row.getSectionType())) {
|
||||
row.setDrugWeighPos(null);
|
||||
}
|
||||
tcuMapper.insert(row);
|
||||
rows.add(row);
|
||||
}
|
||||
if (trace != null) {
|
||||
trace.step("buildTcuRows", "rows", rows.size());
|
||||
}
|
||||
if (!rows.isEmpty()) {
|
||||
Db.saveBatch(rows);
|
||||
if (trace != null) {
|
||||
trace.step("batchInsertTcu", "rows", rows.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A45】混炼示方子表批量插入避免保存超时-----------
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
||||
private static int countRows(List<?> rows) {
|
||||
return rows == null ? 0 : rows.size();
|
||||
}
|
||||
|
||||
/** 混炼示方保存性能追踪(临时诊断日志,定位慢步骤) */
|
||||
private static final class SavePerfTrace {
|
||||
private final String action;
|
||||
private final String mainId;
|
||||
private final String specName;
|
||||
private final long startMs = System.currentTimeMillis();
|
||||
private long lastMs = startMs;
|
||||
private final StringBuilder summary = new StringBuilder();
|
||||
|
||||
private SavePerfTrace(String action, MesXslMixingSpec main) {
|
||||
this.action = action;
|
||||
this.mainId = main != null ? main.getId() : null;
|
||||
this.specName = main != null ? main.getSpecName() : null;
|
||||
summary.append("action=").append(action);
|
||||
if (StringUtils.isNotBlank(mainId)) {
|
||||
summary.append(", mainId=").append(mainId);
|
||||
}
|
||||
if (StringUtils.isNotBlank(specName)) {
|
||||
summary.append(", specName=").append(specName);
|
||||
}
|
||||
}
|
||||
|
||||
private void logPayloadSize(
|
||||
List<MesXslMixingSpecMaterial> materialList,
|
||||
List<MesXslMixingSpecStep> stepList,
|
||||
List<MesXslMixingSpecDownStep> downStepList,
|
||||
List<MesXslMixingSpecTcu> tcuList) {
|
||||
log.info(
|
||||
"[混炼示方保存性能] 开始{} specName={}, mainId={}, payload=[material={}, step={}, downStep={}, tcu={}]",
|
||||
action,
|
||||
specName,
|
||||
mainId,
|
||||
countRows(materialList),
|
||||
countRows(stepList),
|
||||
countRows(downStepList),
|
||||
countRows(tcuList));
|
||||
}
|
||||
|
||||
private void step(String stepName, Object... kvPairs) {
|
||||
long now = System.currentTimeMillis();
|
||||
long stepMs = now - lastMs;
|
||||
long totalMs = now - startMs;
|
||||
summary.append(" | ").append(stepName).append('=').append(stepMs).append("ms");
|
||||
if (kvPairs != null && kvPairs.length > 0) {
|
||||
summary.append('(');
|
||||
for (int i = 0; i < kvPairs.length; i += 2) {
|
||||
if (i > 0) {
|
||||
summary.append(", ");
|
||||
}
|
||||
summary.append(kvPairs[i]).append('=').append(kvPairs[i + 1]);
|
||||
}
|
||||
summary.append(')');
|
||||
}
|
||||
log.info("[混炼示方保存性能] {} 步骤={} 本步耗时={}ms 累计={}ms", action, stepName, stepMs, totalMs);
|
||||
lastMs = now;
|
||||
}
|
||||
|
||||
private void finish() {
|
||||
log.info("[混炼示方保存性能] 完成{} 总耗时={}ms | {}", action, System.currentTimeMillis() - startMs, summary);
|
||||
}
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A41】橡胶及配合剂明细累计按种类分组合计-----------
|
||||
/** 按种类连续分组,累计写入每组最后一行 */
|
||||
private void fillMaterialAccumWeight(List<MesXslMixingSpecMaterial> materials) {
|
||||
if (CollectionUtils.isEmpty(materials)) {
|
||||
return;
|
||||
}
|
||||
int index = 0;
|
||||
while (index < materials.size()) {
|
||||
MesXslMixingSpecMaterial current = materials.get(index);
|
||||
if (!isMaterialDataRow(current)) {
|
||||
current.setAccumWeight(null);
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
String kind = normalizeMaterialKind(current);
|
||||
int groupEnd = index;
|
||||
BigDecimal sum = BigDecimal.ZERO;
|
||||
while (groupEnd < materials.size()) {
|
||||
MesXslMixingSpecMaterial row = materials.get(groupEnd);
|
||||
if (!isMaterialDataRow(row) || !kind.equals(normalizeMaterialKind(row))) {
|
||||
break;
|
||||
}
|
||||
if (row.getUnitWeight() != null) {
|
||||
sum = sum.add(row.getUnitWeight());
|
||||
}
|
||||
groupEnd++;
|
||||
}
|
||||
for (int rowIndex = index; rowIndex < groupEnd; rowIndex++) {
|
||||
if (rowIndex == groupEnd - 1) {
|
||||
materials.get(rowIndex).setAccumWeight(sum.compareTo(BigDecimal.ZERO) != 0 ? sum : null);
|
||||
} else {
|
||||
materials.get(rowIndex).setAccumWeight(null);
|
||||
}
|
||||
}
|
||||
index = groupEnd;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMaterialDataRow(MesXslMixingSpecMaterial row) {
|
||||
if (row == null) {
|
||||
return false;
|
||||
}
|
||||
return StringUtils.isNotBlank(row.getMixerMaterialName())
|
||||
|| row.getUnitWeight() != null
|
||||
|| StringUtils.isNotBlank(row.getMaterialKind());
|
||||
}
|
||||
|
||||
private String normalizeMaterialKind(MesXslMixingSpecMaterial row) {
|
||||
return StringUtils.isNotBlank(row.getMaterialKind()) ? row.getMaterialKind().trim() : "";
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A41】橡胶及配合剂明细累计按种类分组合计-----------
|
||||
|
||||
private List<MesXslMixingSpecMaterial> queryMaterialByMainId(String mainId) {
|
||||
return materialMapper.selectList(
|
||||
@@ -336,4 +614,112 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A49】删除混炼示方时同步删除B/F段胶密炼物料-----------
|
||||
/**
|
||||
* 删除混炼示方后,若该示方编号已无其它混炼示方且未被其它示方明细引用,则同步删除生成时写入的 B/F 段胶密炼物料。
|
||||
*/
|
||||
private void syncDeleteGeneratedRubberMixerMaterial(String specName) {
|
||||
if (StringUtils.isBlank(specName)) {
|
||||
return;
|
||||
}
|
||||
String specCode = specName.trim();
|
||||
Boolean isFinalStage = resolveGeneratedRubberSegment(specCode);
|
||||
if (isFinalStage == null) {
|
||||
return;
|
||||
}
|
||||
long remainingSpecCount =
|
||||
this.count(new LambdaQueryWrapper<MesXslMixingSpec>().eq(MesXslMixingSpec::getSpecName, specCode));
|
||||
if (remainingSpecCount > 0) {
|
||||
log.debug("[混炼示方删除] 示方编号 {} 仍有 {} 条混炼示方,跳过密炼物料同步删除", specCode, remainingSpecCount);
|
||||
return;
|
||||
}
|
||||
long referencedCount = materialMapper.selectCount(
|
||||
new LambdaQueryWrapper<MesXslMixingSpecMaterial>().eq(MesXslMixingSpecMaterial::getMixerMaterialName, specCode));
|
||||
if (referencedCount > 0) {
|
||||
log.info(
|
||||
"[混炼示方删除] 示方编号 {} 仍被 {} 条混炼示方明细引用,跳过密炼物料同步删除",
|
||||
specCode,
|
||||
referencedCount);
|
||||
return;
|
||||
}
|
||||
MesMixerMaterial material = findMixerMaterialByCodeOrName(specCode);
|
||||
if (material == null) {
|
||||
log.debug("[混炼示方删除] 未找到示方编号 {} 对应密炼物料,跳过同步删除", specCode);
|
||||
return;
|
||||
}
|
||||
Map<String, String> categoryIdCache = new HashMap<>();
|
||||
if (!isGeneratedRubberMixerMaterial(material, isFinalStage, categoryIdCache)) {
|
||||
log.info(
|
||||
"[混炼示方删除] 密炼物料 id={}, code={} 分类非生成示方自动同步类型,跳过删除",
|
||||
material.getId(),
|
||||
specCode);
|
||||
return;
|
||||
}
|
||||
mesMixerMaterialService.removeById(material.getId());
|
||||
log.info("[混炼示方删除] 同步删除密炼物料 id={}, code={}", material.getId(), specCode);
|
||||
}
|
||||
|
||||
/** 判断是否为生成混炼示方时自动同步的 B/F 段胶示方编号;true=F段,false=B段,null=非自动生成胶料编号 */
|
||||
private Boolean resolveGeneratedRubberSegment(String specCode) {
|
||||
if (StringUtils.isBlank(specCode)) {
|
||||
return null;
|
||||
}
|
||||
String normalized = specCode.trim();
|
||||
if (normalized.toUpperCase().startsWith("F")) {
|
||||
return true;
|
||||
}
|
||||
if (GENERATED_B_RUBBER_SPEC_PATTERN.matcher(normalized).find()) {
|
||||
return false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private MesMixerMaterial findMixerMaterialByCodeOrName(String specCode) {
|
||||
MesMixerMaterial byCode = mesMixerMaterialService.getOne(
|
||||
new LambdaQueryWrapper<MesMixerMaterial>()
|
||||
.eq(MesMixerMaterial::getMaterialCode, specCode)
|
||||
.and(w -> w.eq(MesMixerMaterial::getDelFlag, CommonConstant.DEL_FLAG_0).or().isNull(MesMixerMaterial::getDelFlag))
|
||||
.last("limit 1"));
|
||||
if (byCode != null) {
|
||||
return byCode;
|
||||
}
|
||||
return mesMixerMaterialService.getOne(
|
||||
new LambdaQueryWrapper<MesMixerMaterial>()
|
||||
.eq(MesMixerMaterial::getMaterialName, specCode)
|
||||
.and(w -> w.eq(MesMixerMaterial::getDelFlag, CommonConstant.DEL_FLAG_0).or().isNull(MesMixerMaterial::getDelFlag))
|
||||
.last("limit 1"));
|
||||
}
|
||||
|
||||
private boolean isGeneratedRubberMixerMaterial(
|
||||
MesMixerMaterial material, boolean isFinalStage, Map<String, String> categoryIdCache) {
|
||||
if (material == null) {
|
||||
return false;
|
||||
}
|
||||
String majorCode = isFinalStage ? CATEGORY_FINAL_MAJOR : CATEGORY_MASTER_MAJOR;
|
||||
String minorCode = isFinalStage ? CATEGORY_FINAL_MINOR_Q : CATEGORY_MASTER_MINOR_A;
|
||||
String expectedMajorId = resolveCategoryIdByCode(majorCode, categoryIdCache);
|
||||
String expectedMinorId = resolveCategoryIdByCode(minorCode, categoryIdCache);
|
||||
if (StringUtils.isBlank(expectedMajorId) || StringUtils.isBlank(expectedMinorId)) {
|
||||
return false;
|
||||
}
|
||||
return expectedMajorId.equals(material.getMajorCategoryId()) && expectedMinorId.equals(material.getMinorCategoryId());
|
||||
}
|
||||
|
||||
private String resolveCategoryIdByCode(String categoryCode, Map<String, String> cache) {
|
||||
if (StringUtils.isBlank(categoryCode)) {
|
||||
return null;
|
||||
}
|
||||
if (cache != null && cache.containsKey(categoryCode)) {
|
||||
return cache.get(categoryCode);
|
||||
}
|
||||
SysCategory category = sysCategoryService.getOne(
|
||||
new LambdaQueryWrapper<SysCategory>().eq(SysCategory::getCode, categoryCode.trim()).last("limit 1"));
|
||||
String categoryId = category != null ? category.getId() : null;
|
||||
if (cache != null) {
|
||||
cache.put(categoryCode, categoryId);
|
||||
}
|
||||
return categoryId;
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A49】删除混炼示方时同步删除B/F段胶密炼物料-----------
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user