|
|
|
@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
|
|
|
import com.baomidou.mybatisplus.core.metadata.IPage; |
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
|
|
|
import com.spring.common.exception.XJException; |
|
|
|
import com.spring.modules.oss.entity.SysOssEntity; |
|
|
|
import com.spring.modules.oss.service.SysOssService; |
|
|
|
import com.spring.modules.part.entity.PartInformationEntity; |
|
|
|
@ -434,11 +435,13 @@ public class QuoteDetailServiceImpl extends ServiceImpl<QuoteDetailMapper, Quote |
|
|
|
Optional<QuoteDetailAttribute> deliverQuantity = attributeList.stream().filter(a -> "SHIPPING-DELIVER-QUANTITY".equals(a.getItemNo())).findAny(); |
|
|
|
//运输其他成本 |
|
|
|
Optional<QuoteDetailAttribute> otherShipCost = attributeList.stream().filter(a -> "SHIPPING-OTHER-COST".equals(a.getItemNo())).findAny(); |
|
|
|
// 运输成本/交付数量 |
|
|
|
if (shipCost.isPresent() && deliverQuantity.isPresent()) { |
|
|
|
if (Objects.nonNull(shipCost.get().getNumValue()) && (Objects.nonNull(deliverQuantity.get().getNumValue()) && deliverQuantity.get().getNumValue().compareTo(new BigDecimal(0)) >= 1)) { |
|
|
|
shippingCost = shipCost.get().getNumValue().divide(deliverQuantity.get().getNumValue()); |
|
|
|
} |
|
|
|
} |
|
|
|
// 运输成本/交付数量+运输其他成本 |
|
|
|
if (otherShipCost.isPresent() && Objects.nonNull(otherShipCost.get().getNumValue())){ |
|
|
|
shippingCost = shippingCost.add(otherShipCost.get().getNumValue()); |
|
|
|
} |
|
|
|
@ -578,43 +581,144 @@ public class QuoteDetailServiceImpl extends ServiceImpl<QuoteDetailMapper, Quote |
|
|
|
// BomTree |
|
|
|
quoteDetailBomTreeService.againQuoteDetailBomTree(detail, id); |
|
|
|
|
|
|
|
// 防止复制明细计算失败 |
|
|
|
try { |
|
|
|
//基本信息成本 如 (物料、工艺等) |
|
|
|
calculateTheCostOfBasicInformation(detail); |
|
|
|
|
|
|
|
// 计算利润和成本 (va,margin等) |
|
|
|
calculateQuoteProfitAndCost(detail); |
|
|
|
lambdaUpdate().eq(QuoteDetail::getId, detail.getId()).update(detail); |
|
|
|
}catch (XJException e){ |
|
|
|
throw new RuntimeException(e.getMessage()); |
|
|
|
}catch (Exception e){ |
|
|
|
log.info("复制明细后自动计算异常"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void calculateTheCostOfBasicInformation(QuoteDetail detail) { |
|
|
|
// 计算 |
|
|
|
// Map<String, Object> map = queryQuoteDetailCost(detail); |
|
|
|
// BigDecimal toolCost = (BigDecimal)map.get("toolCost"); |
|
|
|
// BigDecimal packCost = (BigDecimal)map.get("packCost"); |
|
|
|
// BigDecimal shippingCost = (BigDecimal)map.get("shippingCost"); |
|
|
|
// BigDecimal otherCost = (BigDecimal)map.get("otherCost"); |
|
|
|
// BigDecimal unitQuotePrice = (BigDecimal)map.get("unitQuotePrice"); |
|
|
|
// BigDecimal actualQuotePrice = (BigDecimal)map.get("actualQuotePrice"); |
|
|
|
// BigDecimal labourCost = (BigDecimal)map.get("labourCost"); |
|
|
|
// BigDecimal machineCost = (BigDecimal)map.get("machineCost"); |
|
|
|
// BigDecimal manufactureCost = (BigDecimal)map.get("manufactureCost"); |
|
|
|
// BigDecimal testCost = (BigDecimal)map.get("testCost"); |
|
|
|
// BigDecimal elseCost = (BigDecimal)map.get("elseCost"); |
|
|
|
Map<String, Object> map = queryQuoteDetailCost(detail); |
|
|
|
BigDecimal toolCost = (BigDecimal)map.get("toolCost"); |
|
|
|
BigDecimal packCost = (BigDecimal)map.get("packCost"); |
|
|
|
BigDecimal shippingCost = (BigDecimal)map.get("shippingCost"); |
|
|
|
BigDecimal otherCost = (BigDecimal)map.get("otherCost"); |
|
|
|
BigDecimal unitQuotePrice = (BigDecimal)map.get("unitQuotePrice"); |
|
|
|
BigDecimal actualQuotePrice = (BigDecimal)map.get("actualQuotePrice"); |
|
|
|
BigDecimal labourCost = (BigDecimal)map.get("labourCost"); |
|
|
|
BigDecimal machineCost = (BigDecimal)map.get("machineCost"); |
|
|
|
BigDecimal manufactureCost = (BigDecimal)map.get("manufactureCost"); |
|
|
|
BigDecimal testCost = (BigDecimal)map.get("testCost"); |
|
|
|
BigDecimal elseCost = (BigDecimal)map.get("elseCost"); |
|
|
|
// 赋值 |
|
|
|
// detail.setPartCost(unitQuotePrice); |
|
|
|
// detail.setAdjustPartCost(unitQuotePrice); |
|
|
|
// detail.setBomUnYield(actualQuotePrice); |
|
|
|
// detail.setAdjustBomUnYield(actualQuotePrice); |
|
|
|
// detail.setLabourCost(labourCost); |
|
|
|
// detail.setAdjustLabourCost(labourCost); |
|
|
|
// detail.setMachineCost(manufactureCost); |
|
|
|
// detail.setAdjustMachineCost(manufactureCost); |
|
|
|
// detail.setFabricateCost(manufactureCost); |
|
|
|
// detail.setAdjustFabricateCost(manufactureCost); |
|
|
|
// detail.setToolCost(toolCost); |
|
|
|
// detail.setAdjustToolCost(toolCost); |
|
|
|
// detail.setTestCost(testCost); |
|
|
|
// detail.setAdjustTestCost(testCost); |
|
|
|
// detail.setElseCost(elseCost); |
|
|
|
// detail.setAdjustElseCost(elseCost); |
|
|
|
// detail.setPackCost(packCost); |
|
|
|
// detail.setShippingCost(shippingCost); |
|
|
|
// detail.setOtherCost(otherCost); |
|
|
|
// |
|
|
|
// // 修改 |
|
|
|
// lambdaUpdate().eq(QuoteDetail::getId, detail.getId()).update(detail); |
|
|
|
detail.setPartCost(Optional.ofNullable(unitQuotePrice).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setAdjustPartCost(Optional.ofNullable(unitQuotePrice).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setBomUnYield(Optional.ofNullable(actualQuotePrice).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setAdjustBomUnYield(Optional.ofNullable(actualQuotePrice).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setLabourCost(Optional.ofNullable(labourCost).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setAdjustLabourCost(Optional.ofNullable(labourCost).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setMachineCost( Optional.ofNullable(machineCost).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setAdjustMachineCost( Optional.ofNullable(machineCost).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setFabricateCost( Optional.ofNullable(manufactureCost).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setAdjustFabricateCost(Optional.ofNullable(manufactureCost).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setToolCost(Optional.ofNullable(toolCost).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setAdjustToolCost(Optional.ofNullable(toolCost).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setTestCost(Optional.ofNullable(testCost).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setAdjustTestCost(Optional.ofNullable(testCost).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setElseCost(Optional.ofNullable(elseCost).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setAdjustElseCost(Optional.ofNullable(elseCost).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setPackCost(Optional.ofNullable(packCost).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setShippingCost(Optional.ofNullable(shippingCost).orElse(BigDecimal.ZERO)); |
|
|
|
detail.setOtherCost(Optional.ofNullable(otherCost).orElse(BigDecimal.ZERO)); |
|
|
|
// 取本身 |
|
|
|
detail.setManageCost(Optional.ofNullable(detail.getManageCost()).orElse(BigDecimal.ZERO)); |
|
|
|
} |
|
|
|
|
|
|
|
private void calculateQuoteProfitAndCost(QuoteDetail detail) { |
|
|
|
// 处理计算总成本 |
|
|
|
BigDecimal totalCost = detail.getAdjustPartCost() |
|
|
|
.add(detail.getAdjustMachineCost()) |
|
|
|
.add(detail.getAdjustFabricateCost()) |
|
|
|
.add(detail.getAdjustLabourCost()) |
|
|
|
.add(detail.getManageCost()) |
|
|
|
.add(detail.getAdjustElseCost()) |
|
|
|
.add(detail.getAdjustToolCost()) |
|
|
|
.add(detail.getAdjustTestCost()) |
|
|
|
.add(detail.getPackCost()) |
|
|
|
.add(detail.getShippingCost()); |
|
|
|
// 处理额外添加其他成本 |
|
|
|
List<String> calculatedItems = Arrays.asList(Optional.ofNullable(detail.getCalculatedItems()).orElse("").split(",")); |
|
|
|
BigDecimal totalPartCost = BigDecimal.ZERO; // 总物料成本 |
|
|
|
BigDecimal totalElseCost = BigDecimal.ZERO; // 其他额外成本 |
|
|
|
if (calculatedItems.contains("工具")){ |
|
|
|
totalPartCost = totalPartCost.add(detail.getAdjustToolCost()); |
|
|
|
}else { |
|
|
|
totalElseCost = totalElseCost.add(detail.getAdjustToolCost()); |
|
|
|
} |
|
|
|
if (calculatedItems.contains("测试")){ |
|
|
|
totalPartCost = totalPartCost.add(detail.getAdjustTestCost()); |
|
|
|
}else { |
|
|
|
totalElseCost = totalElseCost.add(detail.getAdjustTestCost()); |
|
|
|
} |
|
|
|
if (calculatedItems.contains("其他")){ |
|
|
|
totalPartCost = totalPartCost.add(detail.getAdjustElseCost()); |
|
|
|
}else { |
|
|
|
totalElseCost = totalElseCost.add(detail.getAdjustElseCost()); |
|
|
|
} |
|
|
|
if (calculatedItems.contains("包装")){ |
|
|
|
totalPartCost = totalPartCost.add(detail.getPackCost()); |
|
|
|
}else { |
|
|
|
totalElseCost = totalElseCost.add(detail.getPackCost()); |
|
|
|
} |
|
|
|
if (calculatedItems.contains("运输")){ |
|
|
|
totalPartCost = totalPartCost.add(detail.getShippingCost()); |
|
|
|
}else { |
|
|
|
totalElseCost = totalElseCost.add(detail.getShippingCost()); |
|
|
|
} |
|
|
|
|
|
|
|
// 利润 |
|
|
|
// 复制无法确认使用那种 利润方式直接采用VA |
|
|
|
BigDecimal quoteProfitRate = Optional.ofNullable(detail.getQuoteProfitRate()).orElse(BigDecimal.ZERO); |
|
|
|
// 公式包含Tool +测试+其他+包装+运输 |
|
|
|
BigDecimal otherCost = detail.getToolCost().add(detail.getTestCost()).add(detail.getElseCost()).add(detail.getPackCost()).add(detail.getShippingCost()); |
|
|
|
// 其他成本 + 材料成本 + 机器成本 + 人工成本 |
|
|
|
BigDecimal ttlCost = otherCost.add(detail.getAdjustPartCost()).add(detail.getAdjustMachineCost()).add(detail.getLabourCost()); |
|
|
|
// price被除数 |
|
|
|
BigDecimal val = BigDecimal.ONE; |
|
|
|
try { |
|
|
|
// (1-VA/100) |
|
|
|
val = BigDecimal.ONE.subtract(quoteProfitRate.divide(new BigDecimal("100"), 16, RoundingMode.HALF_UP)); |
|
|
|
}catch (Exception e){ |
|
|
|
throw new XJException("除数为0错误,VA为100;Price¥(ex VAT) = (物料成本+工具成本+运输成本+包装成本)/(1-VA/100)"); |
|
|
|
} |
|
|
|
//price = (物料成本+工具成本+运输成本+包装成本)/(1-value)+其他额外成本 |
|
|
|
BigDecimal quoteTaxTotalPrice = detail.getAdjustPartCost().add(otherCost).divide(val,16, RoundingMode.HALF_UP).add(totalElseCost); |
|
|
|
// contribution = 1-(物料成本+人工成本+工具成本+运输成本+包装成本)/(price-额外其他成本) |
|
|
|
BigDecimal quoteProfitAmount = BigDecimal.ONE.subtract(detail.getAdjustPartCost().add(detail.getAdjustLabourCost()).add(otherCost).divide(quoteTaxTotalPrice.subtract(totalElseCost),16, RoundingMode.HALF_UP)).multiply(new BigDecimal("100")); |
|
|
|
// margin = (price-额外其他成本-总成本)/(price-额外其他成本) |
|
|
|
BigDecimal quoteTaxRate = quoteTaxTotalPrice.subtract(totalElseCost).subtract(ttlCost).divide(quoteTaxTotalPrice.subtract(totalElseCost),16, RoundingMode.HALF_UP); |
|
|
|
quoteTaxRate = quoteTaxRate.multiply(new BigDecimal("100")); |
|
|
|
|
|
|
|
// 未税单价 |
|
|
|
BigDecimal unitPrice = Optional.of(quoteTaxTotalPrice).orElse(BigDecimal.ZERO); |
|
|
|
// 含税单价(未税单价+(未税单价*(税率+其他税率)/100)) |
|
|
|
BigDecimal taxRate = Optional.ofNullable(detail.getTaxRate()).orElse(BigDecimal.ZERO); |
|
|
|
BigDecimal exchangeRate1 = Optional.ofNullable(detail.getExchangeRate1()).orElse(BigDecimal.ZERO); |
|
|
|
BigDecimal taxUnitPrice = unitPrice.add(unitPrice.multiply(taxRate.add(exchangeRate1.divide(new BigDecimal("100"), 16, RoundingMode.HALF_UP)))); |
|
|
|
|
|
|
|
// 外汇后的含税单价 |
|
|
|
BigDecimal currencyTotalCost2 = BigDecimal.ZERO; |
|
|
|
if (Objects.nonNull(detail.getExchangeRate2()) && detail.getExchangeRate2().compareTo(BigDecimal.ZERO) > 0) { |
|
|
|
currencyTotalCost2 = taxUnitPrice.divide(detail.getExchangeRate2(),16, RoundingMode.HALF_UP); |
|
|
|
} |
|
|
|
// 赋值成本 |
|
|
|
detail.setTotalCost(totalCost); |
|
|
|
detail.setQuoteTaxTotalPrice(quoteTaxTotalPrice); |
|
|
|
detail.setQuoteProfitAmount(quoteProfitAmount); |
|
|
|
detail.setQuoteTaxRate(quoteTaxRate); |
|
|
|
detail.setUnitPrice(unitPrice); |
|
|
|
detail.setTaxUnitPrice(taxUnitPrice); |
|
|
|
detail.setQuoteCurrencyTotalCost2(currencyTotalCost2); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
|