package com.jeeplus.modules.supply.particulars.service;

import com.google.common.collect.Lists;
import com.jeeplus.common.utils.StringUtils;
import com.jeeplus.core.persistence.Page;
import com.jeeplus.core.service.CrudService;
import com.jeeplus.modules.supply.judgementBills.entity.SupplyJudgementBills;
import com.jeeplus.modules.supply.materialsProvidedByAForReview.entity.MaterialsProvidedByAForReview;
import com.jeeplus.modules.supply.particulars.entity.SupplyParticulars;
import com.jeeplus.modules.supply.particulars.mapper.SupplyParticularsMapper;
import com.jeeplus.modules.supply.stockOut.entity.SupplyStockOut;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * 超欠供明细service
 * @author: 徐滕
 * @create: 2022-03-02 10:43
 **/
@Service
@Transactional(readOnly = true)
public class SupplyParticularsService extends CrudService<SupplyParticularsMapper, SupplyParticulars> {



    @Override
    public Page<SupplyParticulars> findPage(Page<SupplyParticulars> page, SupplyParticulars supplyParticulars) {
        //如果送审id和项目定义号均为空 则表示没有选择筛选项，则不进行数据查询展示
        if(StringUtils.isBlank(supplyParticulars.getProjectDefinition()) && StringUtils.isBlank(supplyParticulars.getSubmittalsId())){
            return super.findOverPage(page, supplyParticulars);
        }

        return getProjectDefinitionPage(page, supplyParticulars);
    }

    /**
     * 查询项目定义号对应的数据信息
     * @param page
     * @param supplyParticulars
     * @return
     */
    public Page<SupplyParticulars> getProjectDefinitionPage(Page<SupplyParticulars> page, SupplyParticulars supplyParticulars) {

        List<String> projectDefinitionList= Lists.newArrayList();
        //判断送审id是否有值，有值则对其查询所属的所有项目定义号
        if(StringUtils.isNotBlank(supplyParticulars.getSubmittalsId())){
            //根据送审id查询项目定义号
            projectDefinitionList = mapper.getProjectDefinitionListBySubmittalsId(supplyParticulars.getSubmittalsId());
        }else{
            //根据项目定义号查询出库表某个或某几个项目定义号的所有出库数据
            //项目定义号以；隔开
            if(!"".equals(supplyParticulars.getProjectDefinition())){
                String[] split = supplyParticulars.getProjectDefinition().split(";");
                projectDefinitionList = Arrays.asList(split);
            }
        }
        if(projectDefinitionList.size()>0){
            Set projectDefinitionSet = new HashSet(projectDefinitionList);
            projectDefinitionList = new ArrayList<>(projectDefinitionSet);
        }


        //根据项目定义号查询出库表信息
        List<SupplyStockOut> supplyStockOutList;
        Map<String, List<SupplyStockOut>> supplyStockOutListMap;
        //判定送审id是否为空
        //不为空则先通过送审id查询出库单中对应的项目定义号的信息
        if(StringUtils.isNotBlank(supplyParticulars.getSubmittalsId())){
            supplyStockOutList = mapper.getSupplyStockOutList(projectDefinitionList,supplyParticulars.getSubmittalsId());

            //对出库单数据进行分组
            supplyStockOutListMap = this.groupSupplyStockOut(supplyStockOutList);


            //查询甲供材申报songshenid对应材料的数据和(根据物料编码进行分组)
            List<SupplyStockOut> materialsProvidedByAForReviewList = mapper.getMaterialsProvidedByAForReviewList(supplyParticulars.getSubmittalsId());
            //对甲供材数据进行分组（根据项目定义号进行分组）
            Map<String, List<SupplyStockOut>> materialsProvidedByAForReviewMap = this.groupSupplyStockOut(materialsProvidedByAForReviewList);
            //对出库单数据和甲供材数据进行处理
            List<SupplyStockOut> newSupplyStockOutList = disposeMaterialsDataMap(supplyStockOutListMap, materialsProvidedByAForReviewMap);

            supplyStockOutList = Lists.newArrayList();
            supplyStockOutList.addAll(newSupplyStockOutList);
            if(supplyStockOutList.size()>0){
                //对出库单数据进行分组
                supplyStockOutListMap = this.groupSupplyStockOut(supplyStockOutList);
            }

        }else{
            supplyStockOutList = mapper.getSupplyStockOutList(projectDefinitionList,supplyParticulars.getSubmittalsId());
            //对出库单数据进行分组
            supplyStockOutListMap = this.groupSupplyStockOut(supplyStockOutList);
        }
        //查询审定单中的数据信息
        List<SupplyJudgementBills> supplyJudgementBillsList = mapper.getSupplyJudgementBillsListList(projectDefinitionList,supplyParticulars.getSubmittalsId());
        //对审定单数据进行分组
        Map<String, List<SupplyJudgementBills>> supplyJudgementBillsListMap = this.groupSupplyJudgementBills(supplyJudgementBillsList);

        List<SupplyParticulars> supplyParticularsList = disposeDataMap(supplyStockOutListMap, supplyJudgementBillsListMap);

        //根据物料编码查询历史出库单该物料所属类型，如果均未查到则归属其他类型，否则添加到对应类型中
        for (SupplyParticulars info: supplyParticularsList) {
            if("-".equals(info.getMaterialsType())){
                String materialsType = mapper.getMaterialsType(info.getMaterialNumber());
                switch (materialsType){
                    case "设备":
                        info.setMaterialsType("设备");
                        break;
                    case "材料":
                        info.setMaterialsType("材料");
                        break;
                    case "-":
                        info.setMaterialsType("-");
                        break;
                }
            }
        }

        //对超欠供明细数据进行分组
        Map<String, List<SupplyParticulars>> supplyParticularsListMap = this.groupByMaterialsType(supplyParticularsList);
        List<SupplyParticulars> particularsList = disposeDataMapByMaterialsType(supplyParticularsListMap);
        if(supplyParticularsList.size() > 0){
            SupplyParticulars supplyParticularsCollect = disposeDataCollect(supplyParticularsList);
            particularsList.add(supplyParticularsCollect);
        }
        int size = 0;
        for (SupplyParticulars info : particularsList) {
            size ++;
            info.setId(String.valueOf(size));
            info.setIndex(String.valueOf(size));
        }
        page.setList(particularsList);
        return page;
    }

    private List<SupplyStockOut> disposeMaterialsDataMap(Map<String, List<SupplyStockOut>> supplyStockOutListMap,Map<String, List<SupplyStockOut>> materialsProvidedByAForReviewMap){
        List<SupplyStockOut> newSupplyStockOutList = Lists.newArrayList();

        Set<String> supplyStockOutListMapKeySet = supplyStockOutListMap.keySet();
        Set<String> materialsProvidedByAForReviewMapKeySet = materialsProvidedByAForReviewMap.keySet();
        List<String> supplyStockOutListMapKeyList = new ArrayList<>(supplyStockOutListMapKeySet);
        List<String> materialsProvidedByAForReviewMapKeyList = new ArrayList<>(materialsProvidedByAForReviewMapKeySet);


        //获取迭代器
        Iterator<String> materialsProvidedByAForReviewMapKey = materialsProvidedByAForReviewMapKeyList.iterator();
        while (materialsProvidedByAForReviewMapKey.hasNext()){
            String stockOutMapKey = materialsProvidedByAForReviewMapKey.next();

            //获取迭代器
            Iterator<String> supplyStockOutListMapKey = supplyStockOutListMapKeyList.iterator();
            while (supplyStockOutListMapKey.hasNext()){
                String stockOutListMapKey = supplyStockOutListMapKey.next();
                if (stockOutMapKey.equals(stockOutListMapKey)){
                    //如果两个key键相同，则表示出库单和审定单均有该项目定义号的数据信息
                    //获取该key键对应的list数据
                    List<SupplyStockOut> supplyStockOutList = supplyStockOutListMap.get(stockOutMapKey);
                    List<SupplyStockOut> materialsProvidedByAForReview = materialsProvidedByAForReviewMap.get(stockOutMapKey);

                    //对相同项目定义号的数据进行处理
                    List<SupplyStockOut> supplyParticularsByMaterialNumberList = disposeMaterialDataList(supplyStockOutList, materialsProvidedByAForReview);
                    if(supplyParticularsByMaterialNumberList.size()>0){
                        newSupplyStockOutList.addAll(supplyParticularsByMaterialNumberList);
                    }
                    supplyStockOutListMapKey.remove();
                    supplyStockOutListMap.remove(stockOutMapKey);
                }
            }

            materialsProvidedByAForReviewMapKey.remove();
            materialsProvidedByAForReviewMap.remove(stockOutMapKey);
        }


        return newSupplyStockOutList;
    }


    /**
     * 出库单数据分组
     * @param supplyStockOutList
     * @return
     */
    public Map<String,List<SupplyStockOut>> groupSupplyStockOut (List<SupplyStockOut> supplyStockOutList){
        Map<String, List<SupplyStockOut>> map = new HashMap<>();
        for(SupplyStockOut stockOut : supplyStockOutList){
            if(map.containsKey(stockOut.getProjectDefinition())){//map中存在此id，将数据存放当前key的map中
                map.get(stockOut.getProjectDefinition()).add(stockOut);
            }else{//map中不存在，新建key，用来存放数据
                List<SupplyStockOut> tmpList = new ArrayList<>();
                tmpList.add(stockOut);
                map.put(stockOut.getProjectDefinition(), tmpList);
            }
        }
        return map;
    }

    /**
     * 审定单数据分组
     * @param supplyJudgementBillsList
     * @return
     */
    public Map<String,List<SupplyJudgementBills>> groupSupplyJudgementBills (List<SupplyJudgementBills> supplyJudgementBillsList){
        Map<String, List<SupplyJudgementBills>> map = new HashMap<>();
        for(SupplyJudgementBills judgementBills : supplyJudgementBillsList){
            if(map.containsKey(judgementBills.getProjectDefinition())){//map中存在此id，将数据存放当前key的map中
                map.get(judgementBills.getProjectDefinition()).add(judgementBills);
            }else{//map中不存在，新建key，用来存放数据
                List<SupplyJudgementBills> tmpList = new ArrayList<>();
                tmpList.add(judgementBills);
                map.put(judgementBills.getProjectDefinition(), tmpList);
            }
        }
        return map;
    }


    /**
     * 超欠供明细表根据材料类型进行分组
     * @param supplyParticulars
     * @return
     */
    public Map<String,List<SupplyParticulars>> groupByMaterialsType (List<SupplyParticulars> supplyParticulars){
        Map<String, List<SupplyParticulars>> map = new HashMap<>();
        for(SupplyParticulars particulars : supplyParticulars){
            if(map.containsKey(particulars.getMaterialsType())){//map中存在此id，将数据存放当前key的map中
                map.get(particulars.getMaterialsType()).add(particulars);
            }else{//map中不存在，新建key，用来存放数据
                List<SupplyParticulars> tmpList = new ArrayList<>();
                tmpList.add(particulars);
                map.put(particulars.getMaterialsType(), tmpList);
            }
        }
        return map;
    }

    private List<SupplyParticulars> disposeDataMapByMaterialsType(Map<String, List<SupplyParticulars>> supplyParticularsMap){
        List<SupplyParticulars> supplyParticularsList = Lists.newArrayList();

        Set<String> supplyParticularsMapKeySet = supplyParticularsMap.keySet();
        List<String> supplyParticularsMapKeyList = new ArrayList<>(supplyParticularsMapKeySet);


        //获取迭代器
        Iterator<String> supplyParticularsMapKey = supplyParticularsMapKeyList.iterator();
        while (supplyParticularsMapKey.hasNext()){
            String particularsMapKey = supplyParticularsMapKey.next();
            //获取迭代器
            switch (particularsMapKey){
                case "设备":
                    List<SupplyParticulars> facilityList = supplyParticularsMap.get("设备");
                    supplyParticularsList.addAll(facilityList);
                    SupplyParticulars facility = disposeDataByMaterialsType(facilityList, "设备");
                    facility.setShowType("设备");
                    supplyParticularsList.add(facility);
                    break;
                case "材料":
                    List<SupplyParticulars> materialsList = supplyParticularsMap.get("材料");
                    supplyParticularsList.addAll(materialsList);
                    SupplyParticulars materials = disposeDataByMaterialsType(materialsList, "材料");
                    materials.setShowType("材料");
                    supplyParticularsList.add(materials);
                    break;
                case "-":
                    List<SupplyParticulars> otherList = supplyParticularsMap.get("-");
                    supplyParticularsList.addAll(otherList);
                    SupplyParticulars other = disposeDataByMaterialsType(otherList, "-");
                    other.setShowType("-");
                    supplyParticularsList.add(other);
                    break;
            }
        }

        return supplyParticularsList;
    }

    /**
     * 数据处理
     * @param supplyParticularsList 数据信息
     * @param materialsType 材料类型
     * @return
     */
    private SupplyParticulars disposeDataByMaterialsType(List<SupplyParticulars> supplyParticularsList,String materialsType){
        BigDecimal supplyMoneyB = new BigDecimal(0);
        BigDecimal planMoneyB = new BigDecimal(0);
        BigDecimal practicalMoneyB = new BigDecimal(0);
        for (SupplyParticulars facility : supplyParticularsList) {
            BigDecimal supplyMoney;
            if("-".equals(facility.getSupplyMoney())){
                supplyMoney = new BigDecimal(0);
            }else{
                supplyMoney = new BigDecimal(facility.getSupplyMoney());
            }

            BigDecimal planMoney = new BigDecimal(facility.getPlanMoney());
            BigDecimal practicalMoney = new BigDecimal(facility.getPracticalMoney());
            supplyMoneyB = supplyMoneyB.add(supplyMoney);
            planMoneyB = planMoneyB.add(planMoney);
            practicalMoneyB = practicalMoneyB.add(practicalMoney);
        }

        SupplyParticulars supplyParticulars = new SupplyParticulars();
        supplyParticulars.setBatch("");
        switch (materialsType){
            case "设备":
                supplyParticulars.setMaterialDescription("设备购置费合计");
                break;
            case "材料":
                supplyParticulars.setMaterialDescription("装置性材料费合计");
                break;
            case "-":
                supplyParticulars.setMaterialDescription("其他购置费合计");
                break;
        }
        supplyParticulars.setUnit("");
        supplyParticulars.setActualQuantityIssued("");
        supplyParticulars.setExamineCount("");
        supplyParticulars.setSupplyCount("");
        supplyParticulars.setUnitPrice("");
        String supplyMoneyBStr = supplyMoneyB.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
        String[] supplyMoneyBStrSS = supplyMoneyBStr.split("\\.");
        String supplyMoneyBIntegerStr = supplyMoneyBStrSS[0].replaceAll("(?<=\\d)(?=(?:\\d{3})+$)", ",");
        supplyParticulars.setSupplyMoney(supplyMoneyBIntegerStr + "." + supplyMoneyBStrSS[1]);
        supplyParticulars.setCommodityHandleTenet("");

        String planMoneyBStr = planMoneyB.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
        String[] planMoneyBStrSS = planMoneyBStr.split("\\.");
        String planMoneyBIntegerStr = planMoneyBStrSS[0].replaceAll("(?<=\\d)(?=(?:\\d{3})+$)", ",");
        supplyParticulars.setPlanMoney(planMoneyBIntegerStr + "." + planMoneyBStrSS[1]);

        String practicalMoneyBStr = practicalMoneyB.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
        String[] practicalMoneyBStrSS = practicalMoneyBStr.split("\\.");
        String practicalMoneyBIntegerStr = practicalMoneyBStrSS[0].replaceAll("(?<=\\d)(?=(?:\\d{3})+$)", ",");
        supplyParticulars.setPracticalMoney(practicalMoneyBIntegerStr + "." + practicalMoneyBStrSS[1]);
        supplyParticulars.setSupplyReason("");
        supplyParticulars.setRemarks("");
        supplyParticulars.setFlag("false");
        return supplyParticulars;
    }
    /**
     * 数据汇总处理
     * @param supplyParticularsList 数据信息
     * @return
     */
    private SupplyParticulars disposeDataCollect(List<SupplyParticulars> supplyParticularsList){
        BigDecimal supplyMoneyB = new BigDecimal(0);
        BigDecimal planMoneyB = new BigDecimal(0);
        BigDecimal practicalMoneyB = new BigDecimal(0);
        for (SupplyParticulars facility : supplyParticularsList) {
            BigDecimal supplyMoney;
            if("-".equals(facility.getSupplyMoney())){
                supplyMoney = new BigDecimal(0);
            }else{
                supplyMoney = new BigDecimal(facility.getSupplyMoney());
            }
            BigDecimal planMoney = new BigDecimal(facility.getPlanMoney());
            BigDecimal practicalMoney = new BigDecimal(facility.getPracticalMoney());
            supplyMoneyB = supplyMoneyB.add(supplyMoney);
            planMoneyB = planMoneyB.add(planMoney);
            practicalMoneyB = practicalMoneyB.add(practicalMoney);
        }

        SupplyParticulars supplyParticulars = new SupplyParticulars();
        supplyParticulars.setBatch("");
        supplyParticulars.setMaterialDescription("甲供物资合计");
        supplyParticulars.setUnit("");
        supplyParticulars.setActualQuantityIssued("");
        supplyParticulars.setExamineCount("");
        supplyParticulars.setSupplyCount("");
        supplyParticulars.setUnitPrice("");
        String supplyMoneyBStr = supplyMoneyB.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
        String[] supplyMoneyBStrSS = supplyMoneyBStr.split("\\.");
        String supplyMoneyBIntegerStr = supplyMoneyBStrSS[0].replaceAll("(?<=\\d)(?=(?:\\d{3})+$)", ",");
        supplyParticulars.setSupplyMoney(supplyMoneyBIntegerStr + "." + supplyMoneyBStrSS[1]);
        supplyParticulars.setCommodityHandleTenet("");

        String planMoneyBStr = planMoneyB.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
        String[] planMoneyBStrSS = planMoneyBStr.split("\\.");
        String planMoneyBIntegerStr = planMoneyBStrSS[0].replaceAll("(?<=\\d)(?=(?:\\d{3})+$)", ",");
        supplyParticulars.setPlanMoney(planMoneyBIntegerStr + "." + planMoneyBStrSS[1]);

        String practicalMoneyBStr = practicalMoneyB.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
        String[] practicalMoneyBStrSS = practicalMoneyBStr.split("\\.");
        String practicalMoneyBIntegerStr = practicalMoneyBStrSS[0].replaceAll("(?<=\\d)(?=(?:\\d{3})+$)", ",");
        supplyParticulars.setPracticalMoney(practicalMoneyBIntegerStr + "." + practicalMoneyBStrSS[1]);
        supplyParticulars.setSupplyReason("");
        supplyParticulars.setRemarks("");
        supplyParticulars.setShowType("汇总");
        supplyParticulars.setFlag("false");
        return supplyParticulars;
    }

    private List<SupplyParticulars> disposeDataMap(Map<String, List<SupplyStockOut>> supplyStockOutListMap,Map<String, List<SupplyJudgementBills>> supplyJudgementBillsListMap){
        List<SupplyParticulars> supplyParticularsList = Lists.newArrayList();

        Set<String> supplyStockOutListMapKeySet = supplyStockOutListMap.keySet();
        Set<String> supplyJudgementBillsListMapKeySet = supplyJudgementBillsListMap.keySet();
        List<String> supplyStockOutListMapKeyList = new ArrayList<>(supplyStockOutListMapKeySet);
        List<String> supplyJudgementBillsListMapKeyList = new ArrayList<>(supplyJudgementBillsListMapKeySet);


        //获取迭代器
        Iterator<String> supplyStockOutListMapKey = supplyStockOutListMapKeyList.iterator();
        while (supplyStockOutListMapKey.hasNext()){
            Boolean flag = false;
            String stockOutMapKey = supplyStockOutListMapKey.next();
            //获取迭代器
            Iterator<String> supplyJudgementBillsListMapKey = supplyJudgementBillsListMapKeyList.iterator();
            while (supplyJudgementBillsListMapKey.hasNext()){
                String judgementBillsMapKey = supplyJudgementBillsListMapKey.next();
                if (stockOutMapKey.equals(judgementBillsMapKey)){
                    //如果两个key键相同，则表示出库单和审定单均有该项目定义号的数据信息
                    //获取该key键对应的list数据
                    List<SupplyStockOut> supplyStockOutList = supplyStockOutListMap.get(stockOutMapKey);
                    List<SupplyJudgementBills> supplyJudgementBillsList = supplyJudgementBillsListMap.get(judgementBillsMapKey);

                    //对相同项目定义号的数据进行处理
                    List<SupplyParticulars> supplyParticularsByMaterialNumberList = disposeMaterialNumberDataList(supplyStockOutList, supplyJudgementBillsList);
                    if(supplyParticularsByMaterialNumberList.size()>0){
                        supplyParticularsList.addAll(supplyParticularsByMaterialNumberList);
                    }
                    flag = true;
                    //删除map中对应key键信息
                    supplyJudgementBillsListMapKey.remove();
                    supplyJudgementBillsListMap.remove(judgementBillsMapKey);
                }
            }
            //判定当前出库单是否进行数据处理，如果没有对应审定单则另行处理
            if(!flag){
                List<SupplyStockOut> supplyStockOutList = supplyStockOutListMap.get(stockOutMapKey);
                List<SupplyJudgementBills> supplyJudgementBillsList = Lists.newArrayList();
                //对相同项目定义号的数据进行处理
                List<SupplyParticulars> supplyParticularsByMaterialNumberList = disposeMaterialNumberDataList(supplyStockOutList, supplyJudgementBillsList);
                if(supplyParticularsByMaterialNumberList.size()>0){
                    supplyParticularsList.addAll(supplyParticularsByMaterialNumberList);
                }
            }
            supplyStockOutListMapKey.remove();
            supplyStockOutListMap.remove(stockOutMapKey);
        }

        //判定审定单map列表是否存在未处理的数据，如果存在则对剩余数据进行处理
        if(supplyJudgementBillsListMap.size() > 0){
            Iterator<String> supplyJudgementBillsListMapKey = supplyJudgementBillsListMapKeyList.iterator();
            while (supplyJudgementBillsListMapKey.hasNext()){
                String judgementBillsMapKey = supplyJudgementBillsListMapKey.next();
                List<SupplyStockOut> supplyStockOutList = Lists.newArrayList();
                List<SupplyJudgementBills> supplyJudgementBillsList = supplyJudgementBillsListMap.get(judgementBillsMapKey);

                //对相同项目定义号的数据进行处理
                List<SupplyParticulars> supplyParticularsByMaterialNumberList = disposeMaterialNumberDataList(supplyStockOutList, supplyJudgementBillsList);
                if(supplyParticularsByMaterialNumberList.size()>0){
                    supplyParticularsList.addAll(supplyParticularsByMaterialNumberList);
                }
                //删除map中对应key键信息
                supplyJudgementBillsListMapKey.remove();
                supplyJudgementBillsListMap.remove(judgementBillsMapKey);
            }
        }


        return supplyParticularsList;
    }

    /**
     * 物料编码对应数据处理
     * @param supplyStockOutList
     * @param supplyJudgementBillsList
     * @return
     */
    private List<SupplyParticulars> disposeMaterialNumberDataList(List<SupplyStockOut> supplyStockOutList , List<SupplyJudgementBills> supplyJudgementBillsList){
        List<SupplyParticulars> supplyParticularsList = Lists.newArrayList();
        if (supplyStockOutList.size() == 0 && supplyJudgementBillsList.size() == 0){
            return supplyParticularsList;
        }
        //将出库单根据物料编码进行分组
        Map<String, List<SupplyStockOut>> stockOutMaterialNumberListMap = this.groupSupplyStockOutMaterialNumber(supplyStockOutList);
        //将审定单根据物料编码进行分组
        Map<String, List<SupplyJudgementBills>> judgementBillsMaterialNumberListMap = this.groupSupplyJudgementBillsMaterialNumber(supplyJudgementBillsList);

        //获取所有审定单map对应的key键信息
        Set<String> supplyJudgementBillsListMapKeySet = judgementBillsMaterialNumberListMap.keySet();
        List<String> supplyJudgementBillsListMapKeyList = new ArrayList<>(supplyJudgementBillsListMapKeySet);

        //获取审定单中物料编码对应的出库单中的信息
        Iterator<String> supplyJudgementBillsListMapKey = supplyJudgementBillsListMapKeyList.iterator();
        while (supplyJudgementBillsListMapKey.hasNext()){


            String materialNumber = supplyJudgementBillsListMapKey.next();
            //获取审定单指定数据
            List<SupplyJudgementBills> judgementBillsList = judgementBillsMaterialNumberListMap.get(materialNumber);
            //因为相同物料编码的审定单数据仅存在一条，则通过下标获取特定审定单信息
            SupplyJudgementBills judgementBills = judgementBillsList.get(0);

            //获取出库单中对应的物料编码信息
            List<SupplyStockOut> stockOutMaterialNumberList = stockOutMaterialNumberListMap.get(materialNumber);
            //如果出库单中物料编码数据量大于0，则对数据进行处理
            if(null != stockOutMaterialNumberList && stockOutMaterialNumberList.size()>0){
                //如果出库单对应的物料编码数据量为一条，则将所有的审定数量均放在该数据中
                //如果存在多个并且审定数量高于该条出库单的实发数量 则最大值存放该出库单的实发数量，剩余的往后存放
                if(stockOutMaterialNumberList.size() == 1){
                    SupplyStockOut stockOutMaterialNumber = stockOutMaterialNumberList.get(0);
                    SupplyParticulars supplyParticulars = new SupplyParticulars();

                    supplyParticulars.setMaterialsType(stockOutMaterialNumber.getMaterialsType());
                    supplyParticulars.setExamineCount(judgementBills.getExamineCount());
                    supplyParticulars.setBatch(stockOutMaterialNumber.getBatch());
                    supplyParticulars.setMaterialNumber(stockOutMaterialNumber.getMaterialNumber());
                    supplyParticulars.setMaterialDescription(stockOutMaterialNumber.getMaterialDescription());
                    supplyParticulars.setUnit(stockOutMaterialNumber.getUnit());
                    supplyParticulars.setActualQuantityIssued(stockOutMaterialNumber.getActualQuantityIssued());
                    //审定数量(审定单D列审定数量  保留三位小数)
                    BigDecimal examineCountB = new BigDecimal(judgementBills.getExamineCount());
                    BigDecimal examineCountBs = examineCountB.setScale(3, BigDecimal.ROUND_HALF_UP);
                    supplyParticulars.setExamineCount(examineCountBs.toString());
                    //单价
                    supplyParticulars.setUnitPrice(stockOutMaterialNumber.getUnitPrice());

                    //超（欠）供数量(领用数量-实际耗用数量	当值为0时，显示‘-’)
                    double examineCount = Double.parseDouble(supplyParticulars.getExamineCount());
                    double actualQuantityIssued = Double.parseDouble(supplyParticulars.getActualQuantityIssued());
                    BigDecimal unitPriceB = new BigDecimal(supplyParticulars.getUnitPrice());
                    if(examineCount == actualQuantityIssued){
                        supplyParticulars.setSupplyCount("-");
                        //超（欠）供金额(超欠供数量*材料单价)
                        supplyParticulars.setSupplyMoney("-");
                    }else{
                        supplyParticulars.setSupplyCount(String.valueOf(examineCount - actualQuantityIssued));
                        //超（欠）供金额(超欠供数量*材料单价)
                        BigDecimal supplyCountB = new BigDecimal(supplyParticulars.getSupplyCount());
                        BigDecimal bigDecimal = supplyCountB.multiply(unitPriceB).setScale(2, BigDecimal.ROUND_HALF_UP);
                        supplyParticulars.setSupplyMoney(bigDecimal.toString());
                    }
                    supplyParticulars.setCommodityHandleTenet("");
                    //计划列入工程投资的物资金额(审定数量*单价	金额保留2位小数)
                    BigDecimal examineCountPB = new BigDecimal(supplyParticulars.getExamineCount());
                    BigDecimal bigDecimal = examineCountPB.multiply(unitPriceB).setScale(2, BigDecimal.ROUND_HALF_UP);
                    supplyParticulars.setPlanMoney(bigDecimal.toString());

                    //实际列入工程投资的物资金额
                    BigDecimal actualQuantityIssuedB = new BigDecimal(supplyParticulars.getActualQuantityIssued());
                    BigDecimal actualQuantityIssuedBigDecimal = actualQuantityIssuedB.multiply(unitPriceB).setScale(2, BigDecimal.ROUND_HALF_UP);
                    supplyParticulars.setPracticalMoney(actualQuantityIssuedBigDecimal.toString());
                    supplyParticulars.setProjectDefinition("");
                    supplyParticulars.setRemarks("");
                    supplyParticulars.setFlag("true");
                    supplyParticularsList.add(supplyParticulars);

                }else {
                    int size = stockOutMaterialNumberList.size();
                    int forSize = 0;
                    for (SupplyStockOut stockOutMaterialNumber :stockOutMaterialNumberList) {
                        forSize +=1;
                        SupplyParticulars supplyParticulars = new SupplyParticulars();

                        supplyParticulars.setMaterialsType(stockOutMaterialNumber.getMaterialsType());
                        supplyParticulars.setBatch(stockOutMaterialNumber.getBatch());
                        supplyParticulars.setMaterialNumber(stockOutMaterialNumber.getMaterialNumber());
                        supplyParticulars.setMaterialDescription(stockOutMaterialNumber.getMaterialDescription());
                        supplyParticulars.setUnit(stockOutMaterialNumber.getUnit());
                        supplyParticulars.setActualQuantityIssued(stockOutMaterialNumber.getActualQuantityIssued());

                        double jExamineCount = Double.parseDouble(judgementBills.getExamineCount());
                        double sActualQuantityIssued = Double.parseDouble(stockOutMaterialNumber.getActualQuantityIssued());
                        //如果审定单审定数量超过了出库单出库数量，则将审定单中对应数量去除
                        if(sActualQuantityIssued<jExamineCount){
                            if(size == forSize){

                                BigDecimal b   = new BigDecimal(judgementBills.getExamineCount());
                                BigDecimal f1 = b.setScale(3, BigDecimal.ROUND_HALF_UP);
                                supplyParticulars.setExamineCount(String.valueOf(f1));
                            }else{
                                supplyParticulars.setExamineCount(stockOutMaterialNumber.getActualQuantityIssued());
                            }
                            double examineCountD = Double.parseDouble(judgementBills.getExamineCount());
                            double actualQuantityIssuedD = Double.parseDouble(stockOutMaterialNumber.getActualQuantityIssued());
                            double resultD = examineCountD - actualQuantityIssuedD;
                            BigDecimal b   = new BigDecimal(resultD);
                            double f1 = b.setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue();
                            judgementBills.setExamineCount(String.valueOf(f1));
                        }else{
                            //审定数量(审定单D列审定数量  保留三位小数)
                            BigDecimal examineCountB = new BigDecimal(judgementBills.getExamineCount());
                            BigDecimal examineCountBs = examineCountB.setScale(3, BigDecimal.ROUND_HALF_UP);
                            supplyParticulars.setExamineCount(examineCountBs.toString());
                            judgementBills.setExamineCount("0.000");
                        }
                        //单价
                        supplyParticulars.setUnitPrice(stockOutMaterialNumber.getUnitPrice());

                        //超（欠）供数量(领用数量-实际耗用数量	当值为0时，显示‘-’)
                        BigDecimal examineCountB = new BigDecimal(supplyParticulars.getExamineCount());
                        BigDecimal actualQuantityIssuedB = new BigDecimal(supplyParticulars.getActualQuantityIssued());
                        BigDecimal unitPriceB = new BigDecimal(supplyParticulars.getUnitPrice());
                        if(examineCountB.compareTo(actualQuantityIssuedB) == 0){
                            supplyParticulars.setSupplyCount("-");
                            //超（欠）供金额(超欠供数量*材料单价)
                            supplyParticulars.setSupplyMoney("-");
                        }else{
                            BigDecimal a = examineCountB.subtract(actualQuantityIssuedB).setScale(3, BigDecimal.ROUND_HALF_UP);
                            supplyParticulars.setSupplyCount(String.valueOf(examineCountB.subtract(actualQuantityIssuedB).setScale(3, BigDecimal.ROUND_HALF_UP)));
                            //超（欠）供金额(超欠供数量*材料单价)
                            BigDecimal supplyCountB = new BigDecimal(supplyParticulars.getSupplyCount());
                            BigDecimal bigDecimal = supplyCountB.multiply(unitPriceB).setScale(2, BigDecimal.ROUND_HALF_UP);
                            supplyParticulars.setSupplyMoney(bigDecimal.toString());
                        }
                        supplyParticulars.setCommodityHandleTenet("");
                        //计划列入工程投资的物资金额(审定数量*单价	金额保留2位小数)
                        BigDecimal examineCountPB = new BigDecimal(supplyParticulars.getExamineCount());
                        BigDecimal bigDecimal = examineCountPB.multiply(unitPriceB).setScale(2, BigDecimal.ROUND_HALF_UP);
                        supplyParticulars.setPlanMoney(bigDecimal.toString());

                        //实际列入工程投资的物资金额
                        BigDecimal actualQuantityIssuedBigDecimal = actualQuantityIssuedB.multiply(unitPriceB).setScale(2, BigDecimal.ROUND_HALF_UP);
                        supplyParticulars.setPracticalMoney(actualQuantityIssuedBigDecimal.toString());
                        supplyParticulars.setProjectDefinition("");
                        supplyParticulars.setRemarks("");
                        supplyParticulars.setFlag("true");

                        supplyParticularsList.add(supplyParticulars);

                    }

                }

            }else{
                //如果出库单中物料编码数据量等于0，则表示物料审定后未出库，则没有单价
                //获取历史单价信息并进行求平均数。且不存储批次号

                SupplyParticulars supplyParticulars = new SupplyParticulars();

                supplyParticulars.setMaterialsType("-");
                supplyParticulars.setExamineCount(judgementBills.getExamineCount());
                supplyParticulars.setBatch(null);
                supplyParticulars.setMaterialNumber(judgementBills.getMaterialNumber());
                supplyParticulars.setMaterialDescription(judgementBills.getMaterialDescription());
                supplyParticulars.setUnit(judgementBills.getUnit());
                supplyParticulars.setActualQuantityIssued("0.000");
                //审定数量(审定单D列审定数量  保留三位小数)
                BigDecimal examineCountB = new BigDecimal(judgementBills.getExamineCount());
                BigDecimal examineCountBs = examineCountB.setScale(3, BigDecimal.ROUND_HALF_UP);
                supplyParticulars.setExamineCount(examineCountBs.toString());
                //单价
                //通过物料编码查询物料对应的平均价格
                String avgUtilPriceOnStockOutByMaterialNumber = mapper.getAvgUtilPriceOnStockOutByMaterialNumber(materialNumber);
                supplyParticulars.setUnitPrice(avgUtilPriceOnStockOutByMaterialNumber);

                //超（欠）供数量(领用数量-实际耗用数量	当值为0时，显示‘-’)
                double examineCount = Double.parseDouble(supplyParticulars.getExamineCount());
                double actualQuantityIssued = Double.parseDouble(supplyParticulars.getActualQuantityIssued());
                BigDecimal unitPriceB = new BigDecimal(supplyParticulars.getUnitPrice());
                if(examineCount == actualQuantityIssued){
                    supplyParticulars.setSupplyCount("-");
                    //超（欠）供金额(超欠供数量*材料单价)
                    supplyParticulars.setSupplyMoney("-");
                }else{
                    supplyParticulars.setSupplyCount(String.valueOf(examineCount - actualQuantityIssued));
                    //超（欠）供金额(超欠供数量*材料单价)
                    BigDecimal supplyCountB = new BigDecimal(supplyParticulars.getSupplyCount());
                    BigDecimal bigDecimal = supplyCountB.multiply(unitPriceB).setScale(2, BigDecimal.ROUND_HALF_UP);
                    supplyParticulars.setSupplyMoney(bigDecimal.toString());
                }
                supplyParticulars.setCommodityHandleTenet("");
                //计划列入工程投资的物资金额(审定数量*单价	金额保留2位小数)
                BigDecimal examineCountPB = new BigDecimal(supplyParticulars.getExamineCount());
                BigDecimal bigDecimal = examineCountPB.multiply(unitPriceB).setScale(2, BigDecimal.ROUND_HALF_UP);
                supplyParticulars.setPlanMoney(bigDecimal.toString());

                //实际列入工程投资的物资金额
                BigDecimal actualQuantityIssuedB = new BigDecimal(supplyParticulars.getActualQuantityIssued());
                BigDecimal actualQuantityIssuedBigDecimal = actualQuantityIssuedB.multiply(unitPriceB).setScale(2, BigDecimal.ROUND_HALF_UP);
                supplyParticulars.setPracticalMoney(actualQuantityIssuedBigDecimal.toString());
                supplyParticulars.setProjectDefinition("");
                supplyParticulars.setRemarks("");
                supplyParticulars.setFlag("true");
                supplyParticularsList.add(supplyParticulars);

            }
            //删除map中对应key键信息
            judgementBillsMaterialNumberListMap.remove(materialNumber);
            stockOutMaterialNumberListMap.remove(materialNumber);
        }
        //判断出库单（物料编码）Map是否还存在数据信息
        Set<String> stockOutMaterialNumberListMapKeySet = stockOutMaterialNumberListMap.keySet();
        if(stockOutMaterialNumberListMapKeySet.size()>0){
            List<String> stockOutMaterialNumberListMapKeyList = new ArrayList<>(stockOutMaterialNumberListMapKeySet);
            Iterator<String> stockOutMaterialNumberListMapKey = stockOutMaterialNumberListMapKeyList.iterator();
            while (stockOutMaterialNumberListMapKey.hasNext()){

                String materialNumber = stockOutMaterialNumberListMapKey.next();

                //获取出库单中对应的物料编码信息
                List<SupplyStockOut> stockOutMaterialNumberList = stockOutMaterialNumberListMap.get(materialNumber);
                //如果出库单中物料编码数据量大于0，则对数据进行处理
                if(stockOutMaterialNumberList.size()>0){
                    for (SupplyStockOut stockOutMaterialNumber :stockOutMaterialNumberList) {
                        SupplyParticulars supplyParticulars = new SupplyParticulars();

                        supplyParticulars.setMaterialsType(stockOutMaterialNumber.getMaterialsType());
                        supplyParticulars.setExamineCount("0.000");
                        supplyParticulars.setBatch(stockOutMaterialNumber.getBatch());
                        supplyParticulars.setMaterialNumber(stockOutMaterialNumber.getMaterialNumber());
                        supplyParticulars.setMaterialDescription(stockOutMaterialNumber.getMaterialDescription());
                        supplyParticulars.setUnit(stockOutMaterialNumber.getUnit());
                        supplyParticulars.setActualQuantityIssued(stockOutMaterialNumber.getActualQuantityIssued());
                        //审定数量(审定单D列审定数量  保留三位小数)
                        BigDecimal examineCountB = new BigDecimal("0.000");
                        BigDecimal examineCountBs = examineCountB.setScale(3, BigDecimal.ROUND_HALF_UP);
                        supplyParticulars.setExamineCount(examineCountBs.toString());
                        //单价
                        supplyParticulars.setUnitPrice(stockOutMaterialNumber.getUnitPrice());

                        //超（欠）供数量(领用数量-实际耗用数量	当值为0时，显示‘-’)
                        double examineCount = Double.parseDouble(supplyParticulars.getExamineCount());
                        double actualQuantityIssued = Double.parseDouble(supplyParticulars.getActualQuantityIssued());
                        BigDecimal unitPriceB = new BigDecimal(supplyParticulars.getUnitPrice());
                        if(examineCount == actualQuantityIssued){
                            supplyParticulars.setSupplyCount("-");
                            //超（欠）供金额(超欠供数量*材料单价)
                            supplyParticulars.setSupplyMoney("-");
                        }else{
                            supplyParticulars.setSupplyCount(String.valueOf(examineCount - actualQuantityIssued));
                            //超（欠）供金额(超欠供数量*材料单价)
                            BigDecimal supplyCountB = new BigDecimal(supplyParticulars.getSupplyCount());
                            BigDecimal bigDecimal = supplyCountB.multiply(unitPriceB).setScale(2, BigDecimal.ROUND_HALF_UP);
                            supplyParticulars.setSupplyMoney(bigDecimal.toString());
                        }
                        supplyParticulars.setCommodityHandleTenet("");
                        //计划列入工程投资的物资金额(审定数量*单价	金额保留2位小数)
                        BigDecimal examineCountPB = new BigDecimal(supplyParticulars.getExamineCount());
                        BigDecimal bigDecimal = examineCountPB.multiply(unitPriceB).setScale(2, BigDecimal.ROUND_HALF_UP);
                        supplyParticulars.setPlanMoney(bigDecimal.toString());

                        //实际列入工程投资的物资金额
                        BigDecimal actualQuantityIssuedB = new BigDecimal(supplyParticulars.getActualQuantityIssued());
                        BigDecimal actualQuantityIssuedBigDecimal = actualQuantityIssuedB.multiply(unitPriceB).setScale(2, BigDecimal.ROUND_HALF_UP);
                        supplyParticulars.setPracticalMoney(actualQuantityIssuedBigDecimal.toString());
                        supplyParticulars.setProjectDefinition("");
                        supplyParticulars.setRemarks("");
                        supplyParticulars.setFlag("true");
                        supplyParticularsList.add(supplyParticulars);

                    }
                }
                //删除对应key
                stockOutMaterialNumberListMap.remove(materialNumber);
            }
        }

        return supplyParticularsList;
    }

    /**
     * 物料编码对应数据处理
     * @param supplyStockOutList
     * @param materialsProvidedByAForReviewList
     * @return
     */
    private List<SupplyStockOut> disposeMaterialDataList(List<SupplyStockOut> supplyStockOutList , List<SupplyStockOut> materialsProvidedByAForReviewList){
        List<SupplyStockOut> newSupplyStockOutList = Lists.newArrayList();
        if (supplyStockOutList.size() == 0 && materialsProvidedByAForReviewList.size() == 0){
            return newSupplyStockOutList;
        }
        //将出库单根据物料编码进行分组
        Map<String, List<SupplyStockOut>> stockOutMaterialNumberListMap = this.groupSupplyStockOutMaterialNumber(supplyStockOutList);
        //将审定单根据物料编码进行分组
        Map<String, List<SupplyStockOut>> materialsProvidedByAForReviewListMap = this.groupSupplyStockOutMaterialNumber(materialsProvidedByAForReviewList);

        //获取所有审定单map对应的key键信息
        Set<String> materialsProvidedByAForReviewListMapKeySet = materialsProvidedByAForReviewListMap.keySet();
        List<String> materialsProvidedByAForReviewListMapKeyList = new ArrayList<>(materialsProvidedByAForReviewListMapKeySet);

        //获取审定单中物料编码对应的出库单中的信息
        Iterator<String> materialsProvidedByAForReviewListMapKey = materialsProvidedByAForReviewListMapKeyList.iterator();
        while (materialsProvidedByAForReviewListMapKey.hasNext()){


            String materialNumber = materialsProvidedByAForReviewListMapKey.next();
            //获取审定单指定数据
            List<SupplyStockOut> materialsList = materialsProvidedByAForReviewListMap.get(materialNumber);
            //因为相同物料编码的审定单数据仅存在一条，则通过下标获取特定审定单信息
            SupplyStockOut materials = materialsList.get(0);
            BigDecimal actualQuantityIssued = new BigDecimal(materials.getActualQuantityIssued());
            //获取出库单中对应的物料编码信息
            List<SupplyStockOut> stockOutMaterialNumberList = stockOutMaterialNumberListMap.get(materialNumber);
            if(null != stockOutMaterialNumberList && stockOutMaterialNumberList.size()>0){
                for (SupplyStockOut stockOut : stockOutMaterialNumberList) {
                    BigDecimal stockOutActualQuantityIssued = new BigDecimal(stockOut.getActualQuantityIssued());
                    //比较甲供材送审的物料数量和出库单物料数量
                    //如果出库单物料数量<甲供材送审的物料数量  出库单数据不变
                    //否则甲供材送审的物料数量更替为出库单物料数量
                    if(stockOutActualQuantityIssued.compareTo(actualQuantityIssued) == -1){
                        actualQuantityIssued = actualQuantityIssued.subtract(stockOutActualQuantityIssued);
                        newSupplyStockOutList.add(stockOut);
                    } else{
                        if(actualQuantityIssued.compareTo(new BigDecimal("0.000")) != 0){
                            stockOut.setActualQuantityIssued(actualQuantityIssued.toString());
                            actualQuantityIssued = new BigDecimal("0.000");
                            newSupplyStockOutList.add(stockOut);
                        }
                    }
                }
            }else{
                //如果出库单中没有数据则表示甲供材存在
                //将该条记录存储留用
                //通过物料编码查询物料对应的平均价格
                String avgUtilPriceOnStockOutByMaterialNumber = mapper.getAvgUtilPriceOnStockOutByMaterialNumber(materials.getMaterialNumber());
                materials.setUnitPrice(avgUtilPriceOnStockOutByMaterialNumber);
                //查询材料类型添加金数据中
                String materialsType = mapper.getMaterialsType(materials.getMaterialNumber());
                switch (materialsType){
                    case "设备":
                        materials.setMaterialsType("设备");
                        break;
                    case "材料":
                        materials.setMaterialsType("材料");
                        break;
                    case "-":
                        materials.setMaterialsType("-");
                        break;
                }
                newSupplyStockOutList.add(materials);
            }

            //删除map中对应key键信息
            materialsProvidedByAForReviewListMap.remove(materialNumber);
            stockOutMaterialNumberListMap.remove(materialNumber);
        }

        //获取所有审定单map对应的key键信息
        /*Set<String> stockOutMaterialNumberListMapKeySet = stockOutMaterialNumberListMap.keySet();
        List<String> stockOutMaterialNumberListMapKeyList = new ArrayList<>(stockOutMaterialNumberListMapKeySet);
        for (String infoStr : stockOutMaterialNumberListMapKeyList ) {
            //获取出库单中对应的物料编码信息
            List<SupplyStockOut> stockOutMaterialList = stockOutMaterialNumberListMap.get(infoStr);
            newSupplyStockOutList.addAll(stockOutMaterialList);
        }*/


        return newSupplyStockOutList;
    }



    /**
     * 出库单(物料编码)数据分组
     * @param supplyStockOutList
     * @return
     */
    public Map<String,List<SupplyStockOut>> groupSupplyStockOutMaterialNumber (List<SupplyStockOut> supplyStockOutList){
        Map<String, List<SupplyStockOut>> map = new HashMap<>();
        for(SupplyStockOut stockOut : supplyStockOutList){
            if(map.containsKey(stockOut.getMaterialNumber())){//map中存在此id，将数据存放当前key的map中
                map.get(stockOut.getMaterialNumber()).add(stockOut);
            }else{//map中不存在，新建key，用来存放数据
                List<SupplyStockOut> tmpList = new ArrayList<>();
                tmpList.add(stockOut);
                map.put(stockOut.getMaterialNumber(), tmpList);
            }
        }
        return map;
    }


    /**
     * 审定单(物料编码)数据分组
     * @param supplyJudgementBillsList
     * @return
     */
    public Map<String,List<SupplyJudgementBills>> groupSupplyJudgementBillsMaterialNumber (List<SupplyJudgementBills> supplyJudgementBillsList){
        Map<String, List<SupplyJudgementBills>> map = new HashMap<>();
        for(SupplyJudgementBills stockOut : supplyJudgementBillsList){
            if(map.containsKey(stockOut.getMaterialNumber())){//map中存在此id，将数据存放当前key的map中
                map.get(stockOut.getMaterialNumber()).add(stockOut);
            }else{//map中不存在，新建key，用来存放数据
                List<SupplyJudgementBills> tmpList = new ArrayList<>();
                tmpList.add(stockOut);
                map.put(stockOut.getMaterialNumber(), tmpList);
            }
        }
        return map;
    }

}
