|
|
@ -57,25 +57,32 @@ public class QuoteDetailRoutingServiceImpl extends ServiceImpl<QuoteDetailRoutin |
|
|
List<Long> ids = quoteDetailBomTreeService.getAllChildIds(detail, quoteDetailRouting.getTreeId()); |
|
|
List<Long> ids = quoteDetailBomTreeService.getAllChildIds(detail, quoteDetailRouting.getTreeId()); |
|
|
ids.add(quoteDetailRouting.getTreeId()); |
|
|
ids.add(quoteDetailRouting.getTreeId()); |
|
|
return baseMapper.queryQuoteDetailRoutingByTreeIds(ids).stream().map(o -> { |
|
|
return baseMapper.queryQuoteDetailRoutingByTreeIds(ids).stream().map(o -> { |
|
|
o.setTotalLaborCost(laborCost(o, detail.getQty())); |
|
|
|
|
|
o.setTotalManCost(manufactureCost(o, detail.getQty())); |
|
|
|
|
|
o.setTotalMachCost(machineCost(o, detail.getQty())); |
|
|
|
|
|
|
|
|
|
|
|
o.setTotalCost(o.getTotalLaborCost().add(o.getTotalManCost()).add(o.getTotalMachCost())); |
|
|
|
|
|
|
|
|
fillCosts(o, detail.getQty()); |
|
|
return o; |
|
|
return o; |
|
|
}).collect(Collectors.toList()); |
|
|
}).collect(Collectors.toList()); |
|
|
} |
|
|
} |
|
|
return baseMapper.queryQuoteDetailRouting(quoteDetailRouting).stream().map(o -> { |
|
|
return baseMapper.queryQuoteDetailRouting(quoteDetailRouting).stream().map(o -> { |
|
|
o.setTotalLaborCost(laborCost(o, detail.getQty())); |
|
|
|
|
|
o.setTotalManCost(manufactureCost(o, detail.getQty())); |
|
|
|
|
|
o.setTotalMachCost(machineCost(o, detail.getQty())); |
|
|
|
|
|
|
|
|
|
|
|
o.setTotalCost(o.getTotalLaborCost().add(o.getTotalManCost()).add(o.getTotalMachCost())); |
|
|
|
|
|
|
|
|
fillCosts(o, detail.getQty()); |
|
|
return o; |
|
|
return o; |
|
|
}).collect(Collectors.toList()); |
|
|
}).collect(Collectors.toList()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void fillCosts(QuoteDetailRouting o, BigDecimal qty) { |
|
|
|
|
|
BigDecimal[] laborParts = laborCostParts(o, qty); |
|
|
|
|
|
o.setTotalLaborSetupCost(laborParts[0].setScale(6, RoundingMode.HALF_UP)); |
|
|
|
|
|
o.setTotalLaborRunCost(laborParts[1].setScale(6, RoundingMode.HALF_UP)); |
|
|
|
|
|
o.setTotalLaborCost(laborParts[0].add(laborParts[1]).setScale(6, RoundingMode.HALF_UP)); |
|
|
|
|
|
|
|
|
|
|
|
BigDecimal[] machParts = machineCostParts(o, qty); |
|
|
|
|
|
o.setTotalMachSetupCost(machParts[0].setScale(6, RoundingMode.HALF_UP)); |
|
|
|
|
|
o.setTotalMachRunCost(machParts[1].setScale(6, RoundingMode.HALF_UP)); |
|
|
|
|
|
o.setTotalMachCost(machParts[0].add(machParts[1]).setScale(6, RoundingMode.HALF_UP)); |
|
|
|
|
|
|
|
|
|
|
|
o.setTotalManCost(manufactureCost(o, qty)); |
|
|
|
|
|
o.setTotalCost(o.getTotalLaborCost().add(o.getTotalManCost()).add(o.getTotalMachCost())); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
private BigDecimal unitProcessingTime(QuoteDetailRouting routing, BigDecimal produceQty, BigDecimal moq) { |
|
|
private BigDecimal unitProcessingTime(QuoteDetailRouting routing, BigDecimal produceQty, BigDecimal moq) { |
|
|
BigDecimal processingTime = BigDecimal.ZERO; |
|
|
BigDecimal processingTime = BigDecimal.ZERO; |
|
|
if ("小时".equals(routing.getRunTimeDesc())) { |
|
|
if ("小时".equals(routing.getRunTimeDesc())) { |
|
|
@ -95,53 +102,46 @@ public class QuoteDetailRoutingServiceImpl extends ServiceImpl<QuoteDetailRoutin |
|
|
return processingTime; |
|
|
return processingTime; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private BigDecimal laborCost(QuoteDetailRouting quoteDetailRouting, BigDecimal qty) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 返回 [调机人工成本, 生产人工成本] |
|
|
|
|
|
* 调机:setupLaborClassCost × setupCrewSize × laborSetupTime / MOQ |
|
|
|
|
|
* 生产:laborClassCost × (laborCycleTime / (efficiencyFactor/100) / (1 - shrinkageFactor/100)) × crewSize |
|
|
|
|
|
*/ |
|
|
|
|
|
private BigDecimal[] laborCostParts(QuoteDetailRouting quoteDetailRouting, BigDecimal qty) { |
|
|
BigDecimal setupCost = BigDecimal.ZERO; |
|
|
BigDecimal setupCost = BigDecimal.ZERO; |
|
|
// 调机人员等级成本 |
|
|
|
|
|
BigDecimal setupLaborClassCost = quoteDetailRouting.getSetupLaborClassCost(); |
|
|
BigDecimal setupLaborClassCost = quoteDetailRouting.getSetupLaborClassCost(); |
|
|
// 调机人员数量 |
|
|
|
|
|
BigDecimal setupCrewSize = quoteDetailRouting.getSetupCrewSize(); |
|
|
BigDecimal setupCrewSize = quoteDetailRouting.getSetupCrewSize(); |
|
|
// 人员调机时间 |
|
|
|
|
|
BigDecimal laborSetupTime = quoteDetailRouting.getLaborSetupTime(); |
|
|
BigDecimal laborSetupTime = quoteDetailRouting.getLaborSetupTime(); |
|
|
if (Objects.nonNull(setupLaborClassCost) && Objects.nonNull(setupCrewSize) && Objects.nonNull(laborSetupTime)) { |
|
|
if (Objects.nonNull(setupLaborClassCost) && Objects.nonNull(setupCrewSize) && Objects.nonNull(laborSetupTime)) { |
|
|
if (BigDecimal.ZERO.compareTo(setupLaborClassCost) != 0 && BigDecimal.ZERO.compareTo(setupCrewSize) != 0 && BigDecimal.ZERO.compareTo(laborSetupTime) != 0) { |
|
|
if (BigDecimal.ZERO.compareTo(setupLaborClassCost) != 0 && BigDecimal.ZERO.compareTo(setupCrewSize) != 0 && BigDecimal.ZERO.compareTo(laborSetupTime) != 0) { |
|
|
// 调机人员等级成本*调机人员数量*人员调机时间/moq |
|
|
|
|
|
setupCost = setupLaborClassCost.multiply(setupCrewSize).multiply(laborSetupTime).divide(qty, 16, RoundingMode.HALF_UP); |
|
|
setupCost = setupLaborClassCost.multiply(setupCrewSize).multiply(laborSetupTime).divide(qty, 16, RoundingMode.HALF_UP); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
BigDecimal laborCost = BigDecimal.ZERO; |
|
|
BigDecimal laborCost = BigDecimal.ZERO; |
|
|
// 人员等级成本 |
|
|
|
|
|
BigDecimal laborClassCost = quoteDetailRouting.getLaborClassCost(); |
|
|
BigDecimal laborClassCost = quoteDetailRouting.getLaborClassCost(); |
|
|
// 单位产出 |
|
|
|
|
|
BigDecimal laborCycleTime = BigDecimal.ZERO; |
|
|
BigDecimal laborCycleTime = BigDecimal.ZERO; |
|
|
if (!(Objects.isNull(quoteDetailRouting.getLaborRunFactor()) || BigDecimal.ZERO.compareTo(quoteDetailRouting.getLaborRunFactor()) == 0)) { |
|
|
if (!(Objects.isNull(quoteDetailRouting.getLaborRunFactor()) || BigDecimal.ZERO.compareTo(quoteDetailRouting.getLaborRunFactor()) == 0)) { |
|
|
laborCycleTime = unitProcessingTime(quoteDetailRouting, quoteDetailRouting.getLaborRunFactor(), qty); |
|
|
laborCycleTime = unitProcessingTime(quoteDetailRouting, quoteDetailRouting.getLaborRunFactor(), qty); |
|
|
} |
|
|
} |
|
|
// 效率 |
|
|
|
|
|
BigDecimal efficiencyFactor = quoteDetailRouting.getEfficiencyFactor(); |
|
|
BigDecimal efficiencyFactor = quoteDetailRouting.getEfficiencyFactor(); |
|
|
// 人数 |
|
|
|
|
|
BigDecimal crewSize = quoteDetailRouting.getCrewSize(); |
|
|
BigDecimal crewSize = quoteDetailRouting.getCrewSize(); |
|
|
// 损耗 |
|
|
|
|
|
BigDecimal shrinkageFactor = quoteDetailRouting.getShrinkageFactor(); |
|
|
BigDecimal shrinkageFactor = quoteDetailRouting.getShrinkageFactor(); |
|
|
//人员等级成本*单位产出/效率/(1-损耗率)*人数 |
|
|
|
|
|
// 调机人员等级成本*调机人员数量*人员调机时间/moq+人员等级成本/单位产出/效率/(1-损耗率)*人数 |
|
|
|
|
|
// 单位产出/效率/100 |
|
|
|
|
|
BigDecimal num1 = laborCycleTime.divide(efficiencyFactor.divide(BigDecimal.valueOf(100), 16, RoundingMode.HALF_UP), 16, RoundingMode.HALF_UP); |
|
|
BigDecimal num1 = laborCycleTime.divide(efficiencyFactor.divide(BigDecimal.valueOf(100), 16, RoundingMode.HALF_UP), 16, RoundingMode.HALF_UP); |
|
|
// 单位产出/效率/100/(1-损耗率/100) |
|
|
|
|
|
BigDecimal num2 = BigDecimal.ZERO; |
|
|
BigDecimal num2 = BigDecimal.ZERO; |
|
|
if (Objects.nonNull(shrinkageFactor)) { |
|
|
if (Objects.nonNull(shrinkageFactor)) { |
|
|
num2 = num1.divide(BigDecimal.ONE.subtract(shrinkageFactor.divide(BigDecimal.valueOf(100), 16, RoundingMode.HALF_UP)), 16, RoundingMode.HALF_UP); |
|
|
num2 = num1.divide(BigDecimal.ONE.subtract(shrinkageFactor.divide(BigDecimal.valueOf(100), 16, RoundingMode.HALF_UP)), 16, RoundingMode.HALF_UP); |
|
|
} |
|
|
} |
|
|
// 单位产出/效率/100/(1-损耗率)*人数 |
|
|
|
|
|
if (num2.compareTo(BigDecimal.ZERO) != 0) { |
|
|
if (num2.compareTo(BigDecimal.ZERO) != 0) { |
|
|
|
|
|
|
|
|
// BigDecimal num3 = num2; |
|
|
|
|
|
// 人员等级成本/单位产出/效率/100/(1-损耗率)*人数 |
|
|
|
|
|
laborCost = laborClassCost.multiply(num2).multiply(crewSize); |
|
|
laborCost = laborClassCost.multiply(num2).multiply(crewSize); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return setupCost.add(laborCost).setScale(6, RoundingMode.HALF_UP); |
|
|
|
|
|
|
|
|
return new BigDecimal[]{setupCost, laborCost}; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private BigDecimal laborCost(QuoteDetailRouting quoteDetailRouting, BigDecimal qty) { |
|
|
|
|
|
BigDecimal[] parts = laborCostParts(quoteDetailRouting, qty); |
|
|
|
|
|
return parts[0].add(parts[1]).setScale(6, RoundingMode.HALF_UP); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private BigDecimal manufactureCost(QuoteDetailRouting quoteDetailRouting, BigDecimal qty) { |
|
|
private BigDecimal manufactureCost(QuoteDetailRouting quoteDetailRouting, BigDecimal qty) { |
|
|
@ -165,35 +165,32 @@ public class QuoteDetailRoutingServiceImpl extends ServiceImpl<QuoteDetailRoutin |
|
|
return setupCost; |
|
|
return setupCost; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private BigDecimal machineCost(QuoteDetailRouting quoteDetailRouting, BigDecimal qty) { |
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 返回 [调机机器成本, 生产机器成本] |
|
|
|
|
|
* 调机:workCenterCost × machSetupTime / MOQ |
|
|
|
|
|
* 生产:workCenterCost / (efficiencyFactor/100) × machCycleTime / (1 - shrinkageFactor/100) |
|
|
|
|
|
*/ |
|
|
|
|
|
private BigDecimal[] machineCostParts(QuoteDetailRouting quoteDetailRouting, BigDecimal qty) { |
|
|
BigDecimal setupCost = BigDecimal.ZERO; |
|
|
BigDecimal setupCost = BigDecimal.ZERO; |
|
|
|
|
|
BigDecimal runCost = BigDecimal.ZERO; |
|
|
if (Objects.nonNull(quoteDetailRouting.getWorkCenterCost()) && quoteDetailRouting.getWorkCenterCost().compareTo(BigDecimal.ZERO) > 0) { |
|
|
if (Objects.nonNull(quoteDetailRouting.getWorkCenterCost()) && quoteDetailRouting.getWorkCenterCost().compareTo(BigDecimal.ZERO) > 0) { |
|
|
// 加工中心成本 |
|
|
|
|
|
BigDecimal workCenterCost = quoteDetailRouting.getWorkCenterCost(); |
|
|
BigDecimal workCenterCost = quoteDetailRouting.getWorkCenterCost(); |
|
|
// 调机时间 |
|
|
|
|
|
BigDecimal setupTime = quoteDetailRouting.getMachSetupTime(); |
|
|
BigDecimal setupTime = quoteDetailRouting.getMachSetupTime(); |
|
|
// 加工中心成本*调机时间/moq |
|
|
|
|
|
setupCost = workCenterCost.multiply(setupTime.divide(qty, 16, RoundingMode.HALF_UP)); |
|
|
setupCost = workCenterCost.multiply(setupTime.divide(qty, 16, RoundingMode.HALF_UP)); |
|
|
|
|
|
|
|
|
BigDecimal manufactureCost = BigDecimal.ZERO; |
|
|
|
|
|
// 单位产出 |
|
|
|
|
|
BigDecimal machCycleTime = unitProcessingTime(quoteDetailRouting, quoteDetailRouting.getMachRunFactor(), qty); |
|
|
BigDecimal machCycleTime = unitProcessingTime(quoteDetailRouting, quoteDetailRouting.getMachRunFactor(), qty); |
|
|
// 效率 |
|
|
|
|
|
BigDecimal efficiencyFactor = quoteDetailRouting.getEfficiencyFactor(); |
|
|
BigDecimal efficiencyFactor = quoteDetailRouting.getEfficiencyFactor(); |
|
|
// 损耗率 |
|
|
|
|
|
BigDecimal shrinkageFactor = quoteDetailRouting.getShrinkageFactor(); |
|
|
BigDecimal shrinkageFactor = quoteDetailRouting.getShrinkageFactor(); |
|
|
// 加工中心成本*调机时间/moq+加工中心成本/效率/单位产出/(1-损耗率) |
|
|
|
|
|
// 加工中心成本/效率/单位产出/(1-损耗率) |
|
|
|
|
|
// 加工中心成本/效率/100 |
|
|
|
|
|
BigDecimal num1 = workCenterCost.divide(efficiencyFactor.divide(BigDecimal.valueOf(100), 16, RoundingMode.HALF_UP), 16, RoundingMode.HALF_UP); |
|
|
BigDecimal num1 = workCenterCost.divide(efficiencyFactor.divide(BigDecimal.valueOf(100), 16, RoundingMode.HALF_UP), 16, RoundingMode.HALF_UP); |
|
|
// 加工中心成本/效率/100/单位产出 |
|
|
|
|
|
BigDecimal num2 = num1.multiply(machCycleTime); |
|
|
BigDecimal num2 = num1.multiply(machCycleTime); |
|
|
// 加工中心成本/效率/100/单位产出/(1-损耗率/100) |
|
|
|
|
|
manufactureCost = num2.divide(BigDecimal.ONE.subtract(shrinkageFactor.divide(BigDecimal.valueOf(100), 16, RoundingMode.HALF_UP)), 16, RoundingMode.HALF_UP); |
|
|
|
|
|
|
|
|
|
|
|
setupCost = setupCost.add(manufactureCost); |
|
|
|
|
|
|
|
|
runCost = num2.divide(BigDecimal.ONE.subtract(shrinkageFactor.divide(BigDecimal.valueOf(100), 16, RoundingMode.HALF_UP)), 16, RoundingMode.HALF_UP); |
|
|
} |
|
|
} |
|
|
return setupCost.setScale(6, RoundingMode.HALF_UP); |
|
|
|
|
|
|
|
|
return new BigDecimal[]{setupCost, runCost}; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private BigDecimal machineCost(QuoteDetailRouting quoteDetailRouting, BigDecimal qty) { |
|
|
|
|
|
BigDecimal[] parts = machineCostParts(quoteDetailRouting, qty); |
|
|
|
|
|
return parts[0].add(parts[1]).setScale(6, RoundingMode.HALF_UP); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
|