package com.zzsmart.qomo.kn.cost.manage.plugin;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zzsmart.qomo.kn.cost.manage.entity.*;
import com.zzsmart.qomo.kn.cost.manage.enums.FeeTypeEnum;
import com.zzsmart.qomo.kn.cost.manage.mapper.CostMaterialBomMapper;
import com.zzsmart.qomo.kn.cost.manage.service.*;
import com.zzsmart.qomo.kn.cost.manage.vo.FlowTaskInfoVO;
import com.zzsmart.qomo.plugin.task.api.TaskExecutionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class StandardCostService {
    /**
     * 物料BOM信息
     */
    @Autowired
    CostMaterialBomMapper costMaterialBomMapper;
    @Autowired
    CostMaterialBomService costMaterialBomService;

    /**
     * 小时费率
     */
    @Autowired
    IHourRateService iHourRateService;
    /**
     * 采购单价
     */
    @Autowired
    CostPurchasePriceService costPurchasePriceService;
    /**
     * 工序
     */
    @Autowired
    CostMaterialProcessHoursService costMaterialProcessHoursService;
    /**
     * 标准成本计算结果
     */
    @Autowired
    IAppSceneCostResultValueService iAppSceneCostResultValueService;
    public static StandardCostService standardCostService;
    @Autowired
    IAppSceneCostCountService appSceneCostCountService;


    @PostConstruct
    public void init() {
        standardCostService = this;
        standardCostService.costMaterialBomMapper = this.costMaterialBomMapper;
        standardCostService.appSceneCostCountService = this.appSceneCostCountService;
        standardCostService.costMaterialBomService = this.costMaterialBomService;
        standardCostService.costPurchasePriceService = this.costPurchasePriceService;
        standardCostService.iHourRateService = this.iHourRateService;
        standardCostService.costMaterialProcessHoursService = this.costMaterialProcessHoursService;
        standardCostService.iAppSceneCostResultValueService = this.iAppSceneCostResultValueService;
    }

    /**
     * 更新成本计算模型任务状态
     */
    public static void updateCostCountTaskStatus(Boolean isSuccess, Integer costCountTaskId) {
        log.info("更新成本计算模型任务状态");
        standardCostService.appSceneCostCountService.updateById(AppSceneCostCount.builder().id(costCountTaskId).status(isSuccess != null && isSuccess ? 1 : 0).build());
    }

    /**
     * 1.物料编号输入任务
     */
    public static void materialInputTask(TaskExecutionContext parameters) {
        try {
            //获取任务流程相关信息
            FlowTaskInfoVO flowTaskInfoVO = analysisFlowTaskInfo(parameters);
            //获取最上层的物料号
            String topMaterialCode = flowTaskInfoVO.getTopMaterialCode();
            //获取任务类型
            String taskType = parameters.getTaskType();
            //获取任务代码
            String taskCode = flowTaskInfoVO.getTaskCode();
            //获取流程id
            String flowInstanceId = flowTaskInfoVO.getFlowInstanceId();
            //1.查询出所有满足物料编号的物料（BOM物料）
            String sql = flowTaskInfoVO.getSqlString();
            log.info("传递过来的SQL语句：" + sql);
            List<CostMaterialBom> list = standardCostService.costMaterialBomService.queryAllBomInfoBytopMaterialCode(topMaterialCode);
            log.info("Full EmptyTask list: {}", list);
            //2.把查询的结果存放在临时表里（表命名规则：前缀_流程id_组件code）
            for (int i = 0; list != null && i < list.size(); i++) {
                CostMaterialBom material = list.get(i);
                AppSceneCostResultValue appSceneCostResultValue = AppSceneCostResultValue.builder().belongTopMaterialNo(topMaterialCode).marterialNo(material.getMaterialCode()).parentMarterialNo(material.getParentMaterialCode()).taskType(taskType).taskCode(taskCode).flowInstanceId(flowInstanceId).num(material.getNumber()).build();
                standardCostService.iAppSceneCostResultValueService.save(appSceneCostResultValue);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取任务流程相关信息
     *
     * @param parameters
     * @return
     */
    private static FlowTaskInfoVO analysisFlowTaskInfo(TaskExecutionContext parameters) {
        FlowTaskInfoVO flowTaskInfoVO = new FlowTaskInfoVO();
        if (parameters != null) {
            String s = parameters.toString();
            String[] split = s.split(",");
            for (int i = 0; i < split.length; i++) {
                String s1 = split[i];
                if (s1.contains("taskType")) {
                    String[] split1 = s1.split("=");
                    if (split1[1].contains("\"")) {
                        split1[1] = split1[1].replaceAll("^\"|\"$", ""); // 去除首尾引号
                        flowTaskInfoVO.setTaskType(split1[1]);
                    } else {
                        flowTaskInfoVO.setTaskType(split1[1]);
                    }
                } else if (s1.contains("taskCode")) {
                    String[] split1 = s1.split(":");
                    if (split1[1].contains("\"")) {
                        split1[1] = split1[1].replaceAll("^\"|\"$", ""); // 去除首尾引号
                        flowTaskInfoVO.setTaskCode(split1[1]);
                    } else {
                        flowTaskInfoVO.setTaskCode(split1[1]);
                    }
                } else if (s1.contains("flowInstanceId")) {
                    String[] split1 = s1.split("=");
                    if (split1[1].contains("\"")) {
                        split1[1] = split1[1].replaceAll("^\"|\"$", ""); // 去除首尾引号
                        flowTaskInfoVO.setFlowInstanceId(split1[1]);
                    } else {
                        flowTaskInfoVO.setFlowInstanceId(split1[1]);
                    }
                } else if (s1.contains("sqlString")) {
                    String[] split1 = s1.split(":");
                    if (split1[1].contains("\"")) {
                        split1[1] = split1[1].replaceAll("^\"|\"$", ""); // 去除首尾引号
                        flowTaskInfoVO.setSqlString(split1[1]);
                    } else {
                        flowTaskInfoVO.setSqlString(split1[1]);
                    }
                } else if (s.contains("feeType") && s1.contains("feeType")) {
                    String[] split1 = s1.split(":");
                    if (split1[1].contains("\"")) {
                        split1[1] = split1[1].replaceAll("^\"|\"$", ""); // 去除首尾引号
                        flowTaskInfoVO.setFeeType(split1[1]);
                    } else {
                        flowTaskInfoVO.setFeeType(split1[1]);
                    }
                }
            }
        }
        //通过任务流程id查询流程定义信息（qomo_flow_definition）
        flowTaskInfoVO = queryFlowDefinitionByFlowInstanceId(flowTaskInfoVO);
        return flowTaskInfoVO;
    }

    /**
     * @param flowTaskInfoVO
     */
    private static FlowTaskInfoVO queryFlowDefinitionByFlowInstanceId(FlowTaskInfoVO flowTaskInfoVO) {
        String sql = "SELECT A.model_json from qomo_flow_definition as A LEFT JOIN   qomo_flow_instance AS B ON A.`code`=B.flow_definition_code  WHERE B.id=" + flowTaskInfoVO.getFlowInstanceId() + " limit 1";
        String blob = standardCostService.costMaterialBomMapper.customSelectBlobModelJson(sql);
        if (blob != null) {
            if (blob != null && blob.contains("topMaterialCode")) {
                JSONObject jsonObject1 = JSON.parseObject(blob);
                String topMaterialCode = jsonObject1.getString("topMaterialCode");
                flowTaskInfoVO.setTopMaterialCode(topMaterialCode);
            }
        }
        return flowTaskInfoVO;
    }

    /**
     * 2. 物料成本任务
     */
    public static void materialCostTask(TaskExecutionContext parameters) {
        try {
            //获取任务流程相关信息
            FlowTaskInfoVO flowTaskInfoVO = analysisFlowTaskInfo(parameters);
            //获取最上层的物料号
            String topMaterialCode = flowTaskInfoVO.getTopMaterialCode();
            //获取任务类型
            String taskType = parameters.getTaskType();
            //获取任务代码
            String taskCode = flowTaskInfoVO.getTaskCode();
            //获取流程id
            String flowInstanceId = flowTaskInfoVO.getFlowInstanceId();
            //成本类型
            String feeType = FeeTypeEnum.MaterialCost.getCode();
            //1.查询出物料编号对应的下所有的BOM信息
            List<AppSceneCostResultValue> list = standardCostService.iAppSceneCostResultValueService.getResultValueByTopMaterialNo(topMaterialCode, "MaterialInput", flowInstanceId);
            //2.计算出所有的单个物料的物料成本
            //2.1查询出物料的单价和采购数量
            List<String> MarterialNoList = new ArrayList<>();
            if (list != null && list.size() > 0) {
                MarterialNoList = list.stream().filter(s -> s.getMarterialNo() != null).map(AppSceneCostResultValue::getMarterialNo).collect(Collectors.toList());
            }
            //查询物料的采购价
            Map<String, BigDecimal> purchasePriceMap = standardCostService.costPurchasePriceService.getMinCostPurchasePriceByMaterialNo(MarterialNoList);
            for (int i = 0; i < list.size(); i++) {
                AppSceneCostResultValue appSceneCostResultValue = list.get(i);
                String marterialNo = appSceneCostResultValue.getMarterialNo();
                Integer num = appSceneCostResultValue.getNum();
                if (marterialNo != null && num != null) {
                    BigDecimal price = purchasePriceMap.get(marterialNo);
                    BigDecimal number = new BigDecimal(num.toString());
                    //单价乘以数量
                    BigDecimal totalCost = price.multiply(number);
                    //2.2计算出人工成本并存储到成本结果数据表中
                    AppSceneCostResultValue resultValue = AppSceneCostResultValue.builder().belongTopMaterialNo(topMaterialCode).marterialNo(marterialNo).parentMarterialNo(appSceneCostResultValue.getParentMarterialNo()).taskType(taskType).taskCode(taskCode).flowInstanceId(flowInstanceId).countValue(totalCost + "").build();
                    standardCostService.iAppSceneCostResultValueService.save(resultValue);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 3.人工成本任务
     */
    public static void laborCostTask(TaskExecutionContext parameters) {
        try {
            //获取任务流程相关信息
            FlowTaskInfoVO flowTaskInfoVO = analysisFlowTaskInfo(parameters);
            //获取最上层的物料号
            String topMaterialCode = flowTaskInfoVO.getTopMaterialCode();
            //获取任务类型
            String taskType = parameters.getTaskType();
            //获取任务代码
            String taskCode = flowTaskInfoVO.getTaskCode();
            //获取流程id
            String flowInstanceId = flowTaskInfoVO.getFlowInstanceId();
            //成本类型
            String feeType = FeeTypeEnum.LaborCost.getCode();
            String sql1 = flowTaskInfoVO.getSqlString();
            log.info("sql1:" + sql1);
            String sql = sql1.replaceAll("^\"|\"$", ""); // 去除首尾引号
            log.info("sql:" + sql);
            JSONObject jsonObject = standardCostService.costMaterialBomMapper.customSelectOne(sql);
            BigDecimal hourRate = new BigDecimal("0");
            if (jsonObject != null) {
                HourRate rate = JSON.toJavaObject(jsonObject, HourRate.class);
                hourRate = rate.getLaborHourRate();
            }
            //1.查询出物料编号对应的下所有的BOM信息
            List<AppSceneCostResultValue> list = standardCostService.iAppSceneCostResultValueService.getResultValueByTopMaterialNo(topMaterialCode, "MaterialInput", flowInstanceId);
            //2.计算出所有的单个物料的人工成本
            //2.1查询出物料的人员工时和人工小时费率（涉及：小时费率表和工序表）
            List<String> MarterialNoList = new ArrayList<>();
            if (list != null && list.size() > 0) {
                MarterialNoList = list.stream().filter(s -> s.getMarterialNo() != null).map(AppSceneCostResultValue::getMarterialNo).collect(Collectors.toList());
            }
            //查询工序工时
            Map<String, List<CostMaterialProcessHours>> processHoursMap = standardCostService.costMaterialProcessHoursService.getProcessHoursByMaterialNo(MarterialNoList);
            for (int i = 0; i < list.size(); i++) {
                AppSceneCostResultValue appSceneCostResultValue = list.get(i);
                String marterialNo = appSceneCostResultValue.getMarterialNo();
                if (marterialNo != null) {
                    BigDecimal totalCost = new BigDecimal("0.0");
                    List<CostMaterialProcessHours> costMaterialProcessHours = processHoursMap.get(marterialNo);
                    if (costMaterialProcessHours != null && costMaterialProcessHours.size() > 0) {
                        for (int j = 0; j < costMaterialProcessHours.size(); j++) {
                            CostMaterialProcessHours processHours = costMaterialProcessHours.get(j);
                            BigDecimal laborHours = processHours.getLaborHours();
                            //计算总人工成本
                            totalCost = totalCost.add(laborHours.multiply(hourRate));
                        }
                    }
                    //2.2计算出人工成本并存储到成本结果数据表中
                    AppSceneCostResultValue resultValue = AppSceneCostResultValue.builder().belongTopMaterialNo(topMaterialCode).marterialNo(marterialNo).parentMarterialNo(appSceneCostResultValue.getParentMarterialNo()).taskType(taskType).taskCode(taskCode).flowInstanceId(flowInstanceId).countValue(totalCost + "").costType(feeType).build();
                    standardCostService.iAppSceneCostResultValueService.save(resultValue);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 4.制造费用成本任务
     */
    public static void manufacturingCostTask(TaskExecutionContext parameters) {
        try {
            //获取任务流程相关信息
            FlowTaskInfoVO flowTaskInfoVO = analysisFlowTaskInfo(parameters);
            //获取最上层的物料号
            String topMaterialCode = flowTaskInfoVO.getTopMaterialCode();
            //获取任务类型
            String taskType = parameters.getTaskType();
            //获取任务代码
            String taskCode = flowTaskInfoVO.getTaskCode();
            //获取流程id
            String flowInstanceId = flowTaskInfoVO.getFlowInstanceId();
            /**
             * 费用类别
             */
            String feeType = flowTaskInfoVO.getFeeType();
            /**
             * 小时费率
             */
            String sql1 = flowTaskInfoVO.getSqlString();
            log.info("sql1:" + sql1);
            String sql = sql1.replaceAll("^\"|\"$", ""); // 去除首尾引号
            log.info("sql:" + sql);
            JSONObject jsonObject = standardCostService.costMaterialBomMapper.customSelectOne(sql);
            BigDecimal hourRate = new BigDecimal("0");
            if (jsonObject != null) {
                HourRate rate = JSON.toJavaObject(jsonObject, HourRate.class);
                hourRate = rate.getLaborHourRate();
            }
            //1.查询出物料编号对应的下所有的BOM信息
            List<AppSceneCostResultValue> list = standardCostService.iAppSceneCostResultValueService.getResultValueByTopMaterialNo(topMaterialCode, "MaterialInput", flowInstanceId);
            //2.根据费用类型进行不同的费用计算
            //查询工序工时
            List<String> MarterialNoList = new ArrayList<>();
            if (list != null && list.size() > 0) {
                MarterialNoList = list.stream().filter(s -> s.getMarterialNo() != null).map(AppSceneCostResultValue::getMarterialNo).collect(Collectors.toList());
            }
            Map<String, List<CostMaterialProcessHours>> processHoursMap = standardCostService.costMaterialProcessHoursService.getProcessHoursByMaterialNo(MarterialNoList);
            //2.1机器折旧费（机器工时*费率）
            if (FeeTypeEnum.EquipmentFee.getCode().equals(feeType)) {
                for (int i = 0; i < list.size(); i++) {
                    AppSceneCostResultValue appSceneCostResultValue = list.get(i);
                    String marterialNo = appSceneCostResultValue.getMarterialNo();
                    if (marterialNo != null) {
                        BigDecimal totalCost = new BigDecimal("0.0");
                        List<CostMaterialProcessHours> costMaterialProcessHours = processHoursMap.get(marterialNo);
                        if (costMaterialProcessHours != null && costMaterialProcessHours.size() > 0) {
                            for (int j = 0; j < costMaterialProcessHours.size(); j++) {
                                CostMaterialProcessHours processHours = costMaterialProcessHours.get(j);
                                BigDecimal laborHours = processHours.getDeviceHours();
                                //计算机器成本
                                totalCost = totalCost.add(laborHours.multiply(hourRate));
                            }
                        }
                        //2.2计算机器成本并存储到成本结果数据表中
                        AppSceneCostResultValue resultValue = AppSceneCostResultValue.builder().belongTopMaterialNo(topMaterialCode).marterialNo(marterialNo).parentMarterialNo(appSceneCostResultValue.getParentMarterialNo()).taskType(taskType).taskCode(taskCode).flowInstanceId(flowInstanceId).countValue(totalCost + "").costType(feeType).build();
                        standardCostService.iAppSceneCostResultValueService.save(resultValue);
                    }
                }
            } else if (FeeTypeEnum.SupplyMaterialFee.getCode().equals(feeType)) {
                //机物料消耗（辅料工时*费率）
                for (int i = 0; i < list.size(); i++) {
                    AppSceneCostResultValue appSceneCostResultValue = list.get(i);
                    String marterialNo = appSceneCostResultValue.getMarterialNo();
                    if (marterialNo != null) {
                        BigDecimal totalCost = new BigDecimal("0.0");
                        List<CostMaterialProcessHours> costMaterialProcessHours = processHoursMap.get(marterialNo);
                        if (costMaterialProcessHours != null && costMaterialProcessHours.size() > 0) {
                            for (int j = 0; j < costMaterialProcessHours.size(); j++) {
                                CostMaterialProcessHours processHours = costMaterialProcessHours.get(j);
                                //TODO 辅料工时来源
                                BigDecimal laborHours = processHours.getLaborHours();
                                //机物料消耗
                                totalCost = totalCost.add(laborHours.multiply(hourRate));
                            }
                        }
                        //2.2计算机物料消耗存储到成本结果数据表中
                        AppSceneCostResultValue resultValue = AppSceneCostResultValue.builder().belongTopMaterialNo(topMaterialCode).marterialNo(marterialNo).parentMarterialNo(appSceneCostResultValue.getParentMarterialNo()).taskType(taskType).taskCode(taskCode).flowInstanceId(flowInstanceId).countValue(totalCost + "").costType(feeType).build();
                        standardCostService.iAppSceneCostResultValueService.save(resultValue);
                    }
                }
            } else if (FeeTypeEnum.DriverFee.getCode().equals(feeType)) {
                //2.3水电费（燃动力工时*费率）
                for (int i = 0; i < list.size(); i++) {
                    AppSceneCostResultValue appSceneCostResultValue = list.get(i);
                    String marterialNo = appSceneCostResultValue.getMarterialNo();
                    if (marterialNo != null) {
                        BigDecimal totalCost = new BigDecimal("0.0");
                        List<CostMaterialProcessHours> costMaterialProcessHours = processHoursMap.get(marterialNo);
                        if (costMaterialProcessHours != null && costMaterialProcessHours.size() > 0) {
                            for (int j = 0; j < costMaterialProcessHours.size(); j++) {
                                CostMaterialProcessHours processHours = costMaterialProcessHours.get(j);
                                //TODO 燃动力工时来源
                                BigDecimal laborHours = processHours.getLaborHours();
                                //机物料消耗
                                totalCost = totalCost.add(laborHours.multiply(hourRate));
                            }
                        }
                        //2.2计算机物料消耗存储到成本结果数据表中
                        AppSceneCostResultValue resultValue = AppSceneCostResultValue.builder().belongTopMaterialNo(topMaterialCode).marterialNo(marterialNo).parentMarterialNo(appSceneCostResultValue.getParentMarterialNo()).taskType(taskType).taskCode(taskCode).flowInstanceId(flowInstanceId).countValue(totalCost + "").costType(feeType).build();
                        standardCostService.iAppSceneCostResultValueService.save(resultValue);
                    }
                }
            } else if (FeeTypeEnum.OtherFee.getCode().equals(feeType)) {
                //2.4其他制费（其他工时*费率）
                for (int i = 0; i < list.size(); i++) {
                    AppSceneCostResultValue appSceneCostResultValue = list.get(i);
                    String marterialNo = appSceneCostResultValue.getMarterialNo();
                    if (marterialNo != null) {
                        BigDecimal totalCost = new BigDecimal("0.0");
                        List<CostMaterialProcessHours> costMaterialProcessHours = processHoursMap.get(marterialNo);
                        if (costMaterialProcessHours != null && costMaterialProcessHours.size() > 0) {
                            for (int j = 0; j < costMaterialProcessHours.size(); j++) {
                                CostMaterialProcessHours processHours = costMaterialProcessHours.get(j);
                                //TODO 其他工时来源
                                BigDecimal laborHours = processHours.getLaborHours();
                                //机物料消耗
                                totalCost = totalCost.add(laborHours.multiply(hourRate));
                            }
                        }
                        //2.2计算机物料消耗存储到成本结果数据表中
                        AppSceneCostResultValue resultValue = AppSceneCostResultValue.builder().belongTopMaterialNo(topMaterialCode).marterialNo(marterialNo).parentMarterialNo(appSceneCostResultValue.getParentMarterialNo()).taskType(taskType).taskCode(taskCode).flowInstanceId(flowInstanceId).countValue(totalCost + "").costType(feeType).build();
                        standardCostService.iAppSceneCostResultValueService.save(resultValue);
                    }
                }
            } else if (FeeTypeEnum.LogisticsFee.getCode().equals(feeType)) {
                //查出所有的机器折旧费、机物料消耗、水电费、其他制费
                list = standardCostService.iAppSceneCostResultValueService.getResultValueByTopMaterialNo(topMaterialCode, "ManufacturingCost", flowInstanceId);
                //2.5物流费（（机器折旧+机物料消耗+水电费+其他制费）*10.16%）
                //按照物料编号进行分组
                Map<String, List<AppSceneCostResultValue>> materialNoMap = list.stream().collect(Collectors.groupingBy(AppSceneCostResultValue::getMarterialNo));
                for (String key : materialNoMap.keySet()) {
                    List<AppSceneCostResultValue> appSceneCostResultValues = materialNoMap.get(key);
                    BigDecimal totalCost = new BigDecimal("0.0");
                    for (int j = 0; j < appSceneCostResultValues.size(); j++) {
                        AppSceneCostResultValue appSceneCostResultValue = appSceneCostResultValues.get(j);
                        String countValue = appSceneCostResultValue.getCountValue();
                        if (countValue != null) {
                            totalCost = totalCost.add(new BigDecimal(countValue));
                        }
                    }
                    AppSceneCostResultValue resultValue = AppSceneCostResultValue.builder().belongTopMaterialNo(topMaterialCode).marterialNo(key).parentMarterialNo(appSceneCostResultValues.get(0).getParentMarterialNo()).taskType(taskType).taskCode(taskCode).flowInstanceId(flowInstanceId).countValue(totalCost.multiply(new BigDecimal("0.1016")).toString()).costType(feeType).build();
                    standardCostService.iAppSceneCostResultValueService.save(resultValue);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 5.标准成本计算任务
     */
    public static void standardCostTask(TaskExecutionContext parameters) {
        //获取任务流程相关信息
        FlowTaskInfoVO flowTaskInfoVO = analysisFlowTaskInfo(parameters);
        //获取最上层的物料号
        String topMaterialCode = flowTaskInfoVO.getTopMaterialCode();
        //获取任务类型
        String taskType = parameters.getTaskType();
        //获取任务代码
        String taskCode = flowTaskInfoVO.getTaskCode();
        //获取流程id
        String flowInstanceId = flowTaskInfoVO.getFlowInstanceId();
        //1.查询出物料编号对应的下所有的BOM信息
        List<AppSceneCostResultValue> list = standardCostService.iAppSceneCostResultValueService.getResultValueByTopMaterialNo(topMaterialCode, null, flowInstanceId);
        //2.计算出所有的单个物料的本阶的标准成本(标准成本=物料成本+人工成本+制造费用)
        //按照物料编号进行分组
        Map<String, List<AppSceneCostResultValue>> materialNoMap = list.stream().collect(Collectors.groupingBy(AppSceneCostResultValue::getMarterialNo));
        for (String key : materialNoMap.keySet()) {
            List<AppSceneCostResultValue> appSceneCostResultValues = materialNoMap.get(key);
            //本阶成本
            BigDecimal currentCost = new BigDecimal("0.0");
            for (int j = 0; j < appSceneCostResultValues.size(); j++) {
                AppSceneCostResultValue appSceneCostResultValue = appSceneCostResultValues.get(j);
                String countValue = appSceneCostResultValue.getCountValue();
                if (countValue != null) {
                    currentCost = currentCost.add(new BigDecimal(countValue));
                }
            }
            AppSceneCostResultValue resultValue = AppSceneCostResultValue.builder().belongTopMaterialNo(topMaterialCode).marterialNo(key).parentMarterialNo(appSceneCostResultValues.get(0).getParentMarterialNo()).taskType(taskType).taskCode(taskCode).flowInstanceId(flowInstanceId).countValue(currentCost.toString()).build();
            standardCostService.iAppSceneCostResultValueService.save(resultValue);
        }
        //3.计算出所有的单个物料的累计标准成本
        List<AppSceneCostResultValue> standardCostList = standardCostService.iAppSceneCostResultValueService.getResultValueByTopMaterialNo(topMaterialCode, taskType, flowInstanceId);
        //TODO 优化累计成本的计算
        totalCountCost(standardCostList, topMaterialCode, taskType, taskCode, flowInstanceId);
    }

    /**
     * 循环算出各个物料的累计成本
     *
     * @param standardCostList
     * @param topMaterialCode
     * @param taskType
     * @param taskCode
     * @param flowInstanceId
     */
    private static void totalCountCost(List<AppSceneCostResultValue> standardCostList, String topMaterialCode, String taskType, String taskCode, String flowInstanceId) {
        Map<String, List<AppSceneCostResultValue>> parentMaterialNoMap = standardCostList.stream().filter(appSceneCostResultValue -> appSceneCostResultValue.getParentMarterialNo() != null).collect(Collectors.groupingBy(AppSceneCostResultValue::getParentMarterialNo));
        for (int i = 0; i < standardCostList.size(); i++) {
            AppSceneCostResultValue oldAppSceneCostResultValue = standardCostList.get(i);
            BigDecimal totalCost = new BigDecimal(oldAppSceneCostResultValue.getCountValue());
            totalCost = loopCount(oldAppSceneCostResultValue, parentMaterialNoMap, topMaterialCode, taskType, taskCode, flowInstanceId, totalCost);
            oldAppSceneCostResultValue.setTotalValue(totalCost.toString());
            standardCostService.iAppSceneCostResultValueService.updateById(oldAppSceneCostResultValue);
            //TODO 更新结果集到标准成本单行查询中去
        }
    }

    /**
     * //循环算出各个物料的累计成本
     * 递归计算出累计成本
     *
     * @param appSceneCostResultValue
     * @param parentMaterialNoMap
     * @param topMaterialCode
     * @param taskType
     * @param taskCode
     * @param flowInstanceId
     */
    private static BigDecimal loopCount(AppSceneCostResultValue appSceneCostResultValue, Map<String, List<AppSceneCostResultValue>> parentMaterialNoMap, String topMaterialCode, String taskType, String taskCode, String flowInstanceId, BigDecimal totalCost) {
        String marterialNo = appSceneCostResultValue.getMarterialNo();
        if (parentMaterialNoMap.containsKey(marterialNo)) {
            List<AppSceneCostResultValue> appSceneCostResultValues = parentMaterialNoMap.get(marterialNo);
            for (int j = 0; j < appSceneCostResultValues.size(); j++) {
                AppSceneCostResultValue appSceneCostResultValue1 = appSceneCostResultValues.get(j);
                String countValue = appSceneCostResultValue1.getCountValue();
                if (countValue != null) {
                    totalCost = totalCost.add(new BigDecimal(countValue));
                }
                loopCount(appSceneCostResultValue1, parentMaterialNoMap, topMaterialCode, taskType, taskCode, flowInstanceId, totalCost);
            }
        }
        return totalCost;
    }
}
