Browse Source

修改属性自动计算组件

java8
han\hanst 9 months ago
parent
commit
23f78e3b08
  1. 12
      src/main/java/com/xujie/sys/modules/part/controller/PartInformationController.java
  2. 2
      src/main/java/com/xujie/sys/modules/part/mapper/BomManagementMapper.java
  3. 2
      src/main/java/com/xujie/sys/modules/part/service/PartInformationService.java
  4. 275
      src/main/java/com/xujie/sys/modules/part/service/impl/PartInformationServiceImpl.java
  5. 71
      src/main/java/com/xujie/sys/modules/part/service/impl/RoutingManagementServiceImpl.java
  6. 5
      src/main/resources/mapper/part/BomManagementMapper.xml

12
src/main/java/com/xujie/sys/modules/part/controller/PartInformationController.java

@ -572,4 +572,16 @@ public class PartInformationController {
PartInformationVo partInformation = partInformationService.getCopyRowData(part);
return R.ok().put("rows", partInformation);
}
/**
* 重新计算BOM单位用量和Routing机器处理时间
* @param data
* @return
*/
@PostMapping(value="/recalculateBomAndRouting")
@ResponseBody
public R recalculateBomAndRouting(@RequestBody PartNodeVo data) {
partInformationService.recalculateBomAndRouting(data);
return R.ok();
}
}

2
src/main/java/com/xujie/sys/modules/part/mapper/BomManagementMapper.java

@ -49,7 +49,7 @@ public interface BomManagementMapper extends BaseMapper<BomHeaderEntity> {
void deleteBomHeaderByPartNo(BomHeaderEntity data);
void updateBomComponent(BomComponentEntity data);
int updateBomComponent(BomComponentEntity data);
List<OperationEntity> queryOperationList(OperationEntity data);

2
src/main/java/com/xujie/sys/modules/part/service/PartInformationService.java

@ -104,4 +104,6 @@ public interface PartInformationService extends IService<PartInformationEntity>
void commitItemsValue(List<PartSubPropertiesValueData> list);
PartInformationVo getCopyRowData(PartInformationVo part);
void recalculateBomAndRouting(PartNodeVo data);
}

275
src/main/java/com/xujie/sys/modules/part/service/impl/PartInformationServiceImpl.java

@ -17,10 +17,8 @@ import com.xujie.sys.modules.part.mapper.PartInformationMapper;
import com.xujie.sys.modules.part.mapper.QuicklyCreateBomMapper;
import com.xujie.sys.modules.part.mapper.RoutingManagementMapper;
import com.xujie.sys.modules.part.service.PartInformationService;
import com.xujie.sys.modules.part.vo.AgentInformationVo;
import com.xujie.sys.modules.part.vo.LocationInformationVo;
import com.xujie.sys.modules.part.vo.ManufacturerInformationVo;
import com.xujie.sys.modules.part.vo.PartInformationVo;
import com.xujie.sys.modules.part.service.RoutingManagementService;
import com.xujie.sys.modules.part.vo.*;
import com.xujie.sys.modules.report.dao.ProcedureDao;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.DateUtil;
@ -62,6 +60,9 @@ public class PartInformationServiceImpl extends ServiceImpl<PartInformationMappe
@Autowired
private PartInformationServiceImpl partInformationService;
@Autowired
private RoutingManagementService routingManagementService;
@Value("${sys-file.file-path}")
private String filePath;
@ -1026,4 +1027,270 @@ public class PartInformationServiceImpl extends ServiceImpl<PartInformationMappe
public PartInformationVo getCopyRowData(PartInformationVo part) {
return partInformationMapper.getCopyRowData(part);
}
/**
* 重新计算BOM单位用量和Routing机器处理时间
* @param data
*/
@Override
@Transactional
public void recalculateBomAndRouting(PartNodeVo data) {
System.out.println("====== 开始重新计算BOM和Routing ======");
System.out.println("主产品: site=" + data.getSite() + ", partNo=" + data.getPartNo() + ", codeNo=" + data.getCodeNo());
// 获取BOM树中的所有节点物料包括主产品和所有子节点
List<PartNodeVo> partList = partInformationMapper.partInfoByMainPart(data);
System.out.println("查询到BOM树节点数量: " + (partList != null ? partList.size() : 0));
if (partList != null && !partList.isEmpty()) {
System.out.println("BOM树节点列表:");
for (int i = 0; i < partList.size(); i++) {
PartNodeVo p = partList.get(i);
System.out.println(" " + (i+1) + ". partNo=" + p.getPartNo() + ", partDesc=" + p.getPartDesc() + ", nodeId=" + p.getNodeId());
}
System.out.println("\n开始遍历所有节点,重新计算BOM组件单位用量和Routing:");
for (PartNodeVo part : partList) {
System.out.println("\n========== 处理节点: " + part.getPartNo() + " (" + part.getPartDesc() + ") ==========");
// 1. 重新计算该节点的BOM组件单位用量
recalculateBomComponents(part);
// 2. 重新计算该节点的Routing机器处理时间
recalculateRoutingTime(part);
}
}
System.out.println("\n====== 重新计算完成 ======");
}
/**
* 重新计算BOM单位用量
* @param part
*/
private void recalculateBomComponents(PartNodeVo part) {
System.out.println(" >> 查询节点BOM: partNo=" + part.getPartNo());
// 查询该物料的所有BOM
QueryWrapper<BomHeaderEntity> headerWrapper = new QueryWrapper<>();
headerWrapper.eq("site", part.getSite())
.eq("bu_no", part.getBuNo())
.eq("part_no", part.getPartNo());
List<BomHeaderEntity> bomHeaders = bomManagementMapper.selectList(headerWrapper);
if (bomHeaders == null || bomHeaders.isEmpty()) {
System.out.println(" >> 该节点没有BOM,跳过");
return;
}
System.out.println(" >> 查询到BOM数量: " + bomHeaders.size());
for (BomHeaderEntity header : bomHeaders) {
// 查询每个BOM的所有替代
BomHeaderEntity detailQuery = new BomHeaderEntity();
detailQuery.setSite(header.getSite());
detailQuery.setBuNo(header.getBuNo());
detailQuery.setPartNo(header.getPartNo());
detailQuery.setEngChgLevel(header.getEngChgLevel());
detailQuery.setBomType(header.getBomType());
List<BomDetailEntity> details = bomManagementMapper.queryBomDetail(detailQuery);
System.out.println(" >> 查询到替代数量: " + (details != null ? details.size() : 0));
for (BomDetailEntity detail : details) {
System.out.println(" >> 处理替代: " + detail.getAlternativeNo());
// 查询该替代下的所有组件
BomDetailEntity componentQuery = new BomDetailEntity();
BeanUtils.copyProperties(detail, componentQuery);
List<BomComponentVo> components = bomManagementMapper.queryComponentPart2(componentQuery);
System.out.println(" >> 查询到组件数量: " + (components != null ? components.size() : 0));
if (components == null || components.isEmpty()) {
System.out.println(" >> 该替代没有组件,跳过");
continue;
}
for (BomComponentVo component : components) {
try {
System.out.println(" - 计算组件: " + component.getComponentPart() + " (lineItemNo=" + component.getLineItemNo() + ")");
// 调用存储过程计算单位用量
List<Object> params = new ArrayList<>();
params.add(component.getSite());
params.add(component.getBuNo());
params.add(component.getPartNo());
params.add(component.getComponentPart());
params.add(component.getEngChgLevel());
List<Map<String, Object>> resultList = procedureDao.getProcedureData("RFQ_BOM_Dosage", params);
if (!resultList.isEmpty()) {
Map<String, Object> result = resultList.get(0);
String code = String.valueOf(result.get("resultCode"));
if ("200".equalsIgnoreCase(code)) {
Object qtyObj = result.get("objectId");
BigDecimal qtyPerAssembly = BigDecimal.ZERO;
if (qtyObj instanceof String) {
qtyPerAssembly = new BigDecimal((String) qtyObj);
} else if (qtyObj instanceof Long) {
qtyPerAssembly = BigDecimal.valueOf((Long) qtyObj);
} else if (qtyObj instanceof Double) {
qtyPerAssembly = BigDecimal.valueOf((Double) qtyObj);
} else if (qtyObj instanceof BigDecimal) {
qtyPerAssembly = (BigDecimal) qtyObj;
}
System.out.println(" 原值: " + component.getQtyPerAssembly() + " → 新值: " + qtyPerAssembly);
// 更新单位用量
BomComponentEntity entityToUpdate = new BomComponentEntity();
BeanUtils.copyProperties(component, entityToUpdate);
entityToUpdate.setQtyPerAssembly(qtyPerAssembly);
// 打印更新条件用于诊断
System.out.println(" WHERE条件: site=" + entityToUpdate.getSite()
+ ", partNo=" + entityToUpdate.getPartNo()
+ ", engChgLevel=" + entityToUpdate.getEngChgLevel()
+ ", bomType=" + entityToUpdate.getBomType()
+ ", alternativeNo=" + entityToUpdate.getAlternativeNo()
+ ", lineItemNo=" + entityToUpdate.getLineItemNo());
int updateCount = bomManagementMapper.updateBomComponent(entityToUpdate);
System.out.println(" 更新结果: " + (updateCount > 0 ? "✅ 成功" : "❌ 失败 - 未找到匹配记录"));
if (updateCount == 0) {
System.err.println(" !!! 更新失败,请检查WHERE条件是否正确");
}
}
}
} catch (Exception e) {
System.err.println(" ❌ 计算失败: " + e.getMessage());
e.printStackTrace();
// 忽略单个组件计算失败继续处理下一个
continue;
}
}
}
}
}
/**
* 重新计算Routing机器处理时间
* @param part
*/
private void recalculateRoutingTime(PartNodeVo part) {
System.out.println(" >> 查询节点Routing: partNo=" + part.getPartNo());
// 查询该物料的所有Routing
QueryWrapper<RoutingHeaderEntity> headerWrapper = new QueryWrapper<>();
headerWrapper.eq("site", part.getSite())
.eq("bu_no", part.getBuNo())
.eq("part_no", part.getPartNo());
List<RoutingHeaderEntity> routingHeaders = routingManagementMapper.selectList(headerWrapper);
if (routingHeaders == null || routingHeaders.isEmpty()) {
System.out.println(" >> 该节点没有Routing,跳过");
return;
}
System.out.println(" >> 查询到Routing数量: " + routingHeaders.size());
for (RoutingHeaderEntity header : routingHeaders) {
try {
// 查询每个Routing的所有替代和工序
RoutingDetailEntity detailQuery = new RoutingDetailEntity();
detailQuery.setSite(header.getSite());
detailQuery.setBuNo(header.getBuNo());
detailQuery.setPartNo(header.getPartNo());
detailQuery.setRoutingRevision(header.getRoutingRevision());
detailQuery.setRoutingType(header.getRoutingType());
detailQuery.setAlternativeNo("*");
List<RoutingComponentVo> components = routingManagementMapper.queryRoutingComponent(detailQuery);
if (components != null && !components.isEmpty()) {
// 获取该物料的商品组信息
PartInformationEntity partInfo = partInformationMapper.selectOne(
new QueryWrapper<PartInformationEntity>()
.eq("site", part.getSite())
.eq("sourceBu", part.getBuNo())
.eq("part_no", part.getPartNo())
);
// 从商品组获取标准工序数据
List<RoutingComponentVo> standardOps = null;
if (partInfo != null && partInfo.getProductGroupId1() != null) {
standardOps = routingManagementMapper.getStandardRoutingOperationByProductGroupId(
part.getSite(), part.getBuNo(), partInfo.getProductGroupId1()
);
}
// 构建RoutingHeaderVo用于计算
RoutingHeaderVo headerVo = new RoutingHeaderVo();
BeanUtils.copyProperties(header, headerVo);
// 重要设置该物料的codeNo用于查询属性
headerVo.setCodeNo(part.getCodeNo());
headerVo.setPartNo(part.getPartNo());
headerVo.setSite(part.getSite());
headerVo.setBuNo(part.getBuNo());
// 用标准工序数据填充ref_speed等字段
for (RoutingComponentVo vo : components) {
vo.setFlag("Y"); // 设置flag标识用于计算工时
// 如果ref_speed等字段为空或为0从标准工序获取
if (standardOps != null) {
for (RoutingComponentVo stdOp : standardOps) {
if (stdOp.getOperationName() != null && stdOp.getOperationName().equals(vo.getOperationName())) {
if (vo.getRefSpeed() == null || vo.getRefSpeed().compareTo(BigDecimal.ZERO) == 0) {
vo.setRefSpeed(stdOp.getRefSpeed());
}
if (vo.getRefTime() == null || vo.getRefTime().compareTo(BigDecimal.ZERO) == 0) {
vo.setRefTime(stdOp.getRefTime());
}
if (vo.getRefEfficiency() == null || vo.getRefEfficiency().compareTo(BigDecimal.ZERO) == 0) {
vo.setRefEfficiency(stdOp.getRefEfficiency());
}
if (vo.getRefDailyProduction() == null || vo.getRefDailyProduction().compareTo(BigDecimal.ZERO) == 0) {
vo.setRefDailyProduction(stdOp.getRefDailyProduction());
}
break;
}
}
}
// 确保必要字段不为null
if (vo.getRefSpeed() == null) vo.setRefSpeed(BigDecimal.ZERO);
if (vo.getRefTime() == null) vo.setRefTime(BigDecimal.ZERO);
if (vo.getRefEfficiency() == null) vo.setRefEfficiency(BigDecimal.ZERO);
if (vo.getRefDailyProduction() == null) vo.setRefDailyProduction(BigDecimal.ZERO);
}
headerVo.setOperationList(components);
// 调用计算工时方法
List<RoutingComponentVo> calculatedOperations = routingManagementService.calculationTime(headerVo);
System.out.println(" >> 计算完成,准备更新" + calculatedOperations.size() + "个工序");
// 更新机器处理时间
for (RoutingComponentVo operation : calculatedOperations) {
System.out.println(" - 工序" + operation.getOperationNo() + " " + operation.getOperationName() + ": machCycleTime=" + operation.getMachCycleTime());
RoutingComponentEntity entityToUpdate = new RoutingComponentEntity();
BeanUtils.copyProperties(operation, entityToUpdate);
routingManagementMapper.updateRoutingComponent(entityToUpdate);
}
}
} catch (Exception e) {
System.err.println(" >> 计算失败: " + e.getMessage());
e.printStackTrace();
// 忽略单个Routing计算失败继续处理下一个
continue;
}
}
}
}

71
src/main/java/com/xujie/sys/modules/part/service/impl/RoutingManagementServiceImpl.java

@ -752,7 +752,10 @@ public class RoutingManagementServiceImpl extends ServiceImpl<RoutingManagementM
// 判断工序
if ("一复".equals(operation.getOperationName()) || "熟化".equals(operation.getOperationName()) || "RFID前道检品".equals(operation.getOperationName())) {
// 1 /速度 x 时间 x 效率, 保留四位小数四舍五入
machCycleTime = BigDecimal.ONE.divide(refSpeed.multiply(refTime).multiply(refEfficiency), scale, RoundingMode.HALF_UP);
BigDecimal divisor = refSpeed.multiply(refTime).multiply(refEfficiency);
if (divisor.compareTo(BigDecimal.ZERO) != 0) {
machCycleTime = BigDecimal.ONE.divide(divisor, scale, RoundingMode.HALF_UP);
}
} else if ("印刷".equals(operation.getOperationName()) || "RFID-蚀刻".equals(operation.getOperationName()) || "RFID-分切".equals(operation.getOperationName())) {
// 1 /速度 x 时间 x 效率/ Printing lanes , 保留四位小数四舍五入
List<PartSubPropertiesValueData> collect = partItems.stream().filter(a -> "Printing lanes".equals(a.getItemDesc())).collect(Collectors.toList());
@ -761,10 +764,13 @@ public class RoutingManagementServiceImpl extends ServiceImpl<RoutingManagementM
BigDecimal numValue = BigDecimal.valueOf(collect.get(0).getNumValue());
// 速度 x 时间 x 效率
BigDecimal product = refSpeed.multiply(refTime).multiply(refEfficiency);
// 1 / 速度 x 时间 x 效率
BigDecimal intermediateResult = BigDecimal.ONE.divide(product, scale2, RoundingMode.HALF_UP);
// 最终结果
machCycleTime = intermediateResult.divide(numValue, scale, RoundingMode.HALF_UP);
// 检查除数是否为零
if (product.compareTo(BigDecimal.ZERO) != 0 && numValue.compareTo(BigDecimal.ZERO) != 0) {
// 1 / 速度 x 时间 x 效率
BigDecimal intermediateResult = BigDecimal.ONE.divide(product, scale2, RoundingMode.HALF_UP);
// 最终结果
machCycleTime = intermediateResult.divide(numValue, scale, RoundingMode.HALF_UP);
}
}
} else if ("RFID绑定-TAL".equals(operation.getOperationName()) || "RFID绑定-Paris".equals(operation.getOperationName())
|| "Encoding(编码)".equals(operation.getOperationName()) || "CLS编码打印".equals(operation.getOperationName()) || operation.getOperationName().contains("后道检品")) {
@ -784,10 +790,14 @@ public class RoutingManagementServiceImpl extends ServiceImpl<RoutingManagementM
if (!collect.isEmpty()) {
// UPH 属性的值
BigDecimal numValue = BigDecimal.valueOf(collect.get(0).getNumValue());
// 1/ (UPH x 效率)
BigDecimal product = BigDecimal.ONE.divide(numValue.multiply(refEfficiency), scale2, RoundingMode.HALF_UP);
// 最终结果
machCycleTime = product.multiply(BigDecimal.valueOf(1000)).setScale(scale, RoundingMode.HALF_UP);
BigDecimal divisor = numValue.multiply(refEfficiency);
// 检查除数是否为零
if (divisor.compareTo(BigDecimal.ZERO) != 0) {
// 1/ (UPH x 效率)
BigDecimal product = BigDecimal.ONE.divide(divisor, scale2, RoundingMode.HALF_UP);
// 最终结果
machCycleTime = product.multiply(BigDecimal.valueOf(1000)).setScale(scale, RoundingMode.HALF_UP);
}
}
} else if ("RFID绑定-MLI".equals(operation.getOperationName()) || operation.getOperationName().contains("RFID复合模切检测")
|| operation.getOperationName().contains("RFID自动贴标") || operation.getOperationName().contains("Voyantic在线检测")) {
@ -809,26 +819,41 @@ public class RoutingManagementServiceImpl extends ServiceImpl<RoutingManagementM
collect2 = partItems.stream().filter(a -> "检测列数".equals(a.getItemDesc())).collect(Collectors.toList());
}
if (!collect1.isEmpty() && !collect2.isEmpty()) {
// 1000/pitch
BigDecimal numValue1 = BigDecimal.valueOf(1000).divide(BigDecimal.valueOf(collect1.get(0).getNumValue()), scale2, RoundingMode.HALF_UP);
// 列数 属性的值
BigDecimal numValue2 = BigDecimal.valueOf(collect2.get(0).getNumValue());
// 1 / (速度 x 时间 x 效率 x (1000/pitch) x 列数)
BigDecimal product = BigDecimal.ONE.divide(refSpeed.multiply(refTime).multiply(refEfficiency).multiply(numValue1).multiply(numValue2), scale2, RoundingMode.HALF_UP);
// 最终结果
machCycleTime = product.multiply(BigDecimal.valueOf(1000)).setScale(scale, RoundingMode.HALF_UP);
BigDecimal pitchValue = BigDecimal.valueOf(collect1.get(0).getNumValue());
BigDecimal laneValue = BigDecimal.valueOf(collect2.get(0).getNumValue());
// 检查除数是否为零
if (pitchValue.compareTo(BigDecimal.ZERO) != 0 && laneValue.compareTo(BigDecimal.ZERO) != 0) {
// 1000/pitch
BigDecimal numValue1 = BigDecimal.valueOf(1000).divide(pitchValue, scale2, RoundingMode.HALF_UP);
// 列数 属性的值
BigDecimal numValue2 = laneValue;
// 1 / (速度 x 时间 x 效率 x (1000/pitch) x 列数)
BigDecimal divisor = refSpeed.multiply(refTime).multiply(refEfficiency).multiply(numValue1).multiply(numValue2);
if (divisor.compareTo(BigDecimal.ZERO) != 0) {
BigDecimal product = BigDecimal.ONE.divide(divisor, scale2, RoundingMode.HALF_UP);
// 最终结果
machCycleTime = product.multiply(BigDecimal.valueOf(1000)).setScale(scale, RoundingMode.HALF_UP);
}
}
}
} else if ("Packaging".equals(operation.getOperationName())) {
// (1 / (日产量 * 效率)) x 1000
// 日产量 * 效率
BigDecimal product = BigDecimal.ONE.divide(refDailyProduction.multiply(refEfficiency), scale2, RoundingMode.HALF_UP);
// 最终结果
machCycleTime = product.multiply(BigDecimal.valueOf(1000)).setScale(scale, RoundingMode.HALF_UP);
BigDecimal divisor = refDailyProduction.multiply(refEfficiency);
if (divisor.compareTo(BigDecimal.ZERO) != 0) {
// 日产量 * 效率
BigDecimal product = BigDecimal.ONE.divide(divisor, scale2, RoundingMode.HALF_UP);
// 最终结果
machCycleTime = product.multiply(BigDecimal.valueOf(1000)).setScale(scale, RoundingMode.HALF_UP);
}
}
operation.setMachCycleTime(machCycleTime); // 机器处理时间
operation.setLaborCycleTime(machCycleTime); // 人工处理时间
operation.setMachRunFactor(BigDecimal.ONE.divide(machCycleTime, 4, RoundingMode.HALF_UP)); // 机器单位产出
operation.setLaborRunFactor(BigDecimal.ONE.divide(machCycleTime, 4, RoundingMode.HALF_UP)); // 人工单位产出
// 机器单位产出和人工单位产出
if (machCycleTime.compareTo(BigDecimal.ZERO) != 0) {
operation.setMachRunFactor(BigDecimal.ONE.divide(machCycleTime, 4, RoundingMode.HALF_UP));
operation.setLaborRunFactor(BigDecimal.ONE.divide(machCycleTime, 4, RoundingMode.HALF_UP));
}
}
}
return operations;

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

@ -444,7 +444,7 @@
material_length2 = #{materialLength2},
unit_conversion = #{unitConversion},
component_part = #{componentPart}
where site = #{site} and part_no = #{partNo} and eng_chg_level = #{engChgLevel} and bom_type = #{bomType} and alternative_no = #{alternativeNo} and line_item_no = #{lineItemNo}
where site = #{site} and bu_no = #{buNo} and part_no = #{partNo} and eng_chg_level = #{engChgLevel} and bom_type = #{bomType} and alternative_no = #{alternativeNo} and line_item_no = #{lineItemNo}
</update>
<!-- 修改bom子明细 -->
@ -455,7 +455,7 @@
shrinkage_factor = #{shrinkageFactor},
update_date = getDate(),
update_by = #{updateBy}
where site = #{site} and part_no = #{partNo} and eng_chg_level = #{engChgLevel} and bom_type = #{bomType} and alternative_no = #{alternativeNo} and line_item_no = #{lineItemNo}
where site = #{site} and bu_no = #{buNo} and part_no = #{partNo} and eng_chg_level = #{engChgLevel} and bom_type = #{bomType} and alternative_no = #{alternativeNo} and line_item_no = #{lineItemNo}
</update>
<!-- 查bom明细对象 -->
@ -611,6 +611,7 @@
eng_chg_level,
bom_type,
alternative_no,
line_item_no,
component_part,
qty_per_assembly
FROM plm_bom_component

Loading…
Cancel
Save