package com.bonus.material.settlement.controller;

import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.bonus.common.biz.config.ListPagingUtil;
import com.bonus.common.biz.config.PoiOutPage;
import com.bonus.common.biz.utils.RequestContext;
import com.bonus.common.core.utils.ServletUtils;
import com.bonus.common.log.enums.OperaType;
import com.bonus.common.log.enums.OperatorType;
import com.bonus.material.basic.domain.BmProject;
import com.bonus.material.common.annotation.PreventRepeatSubmit;
import com.bonus.material.common.domain.dto.SelectDto;
import com.bonus.material.settlement.domain.SltAgreementApply;
import com.bonus.material.settlement.domain.SltAgreementReduce;
import com.bonus.material.settlement.domain.SltAgreementRelation;
import com.bonus.material.settlement.domain.vo.SltInfoVo;
import com.bonus.material.settlement.domain.vo.SltLeaseInfo;
import com.bonus.material.settlement.mapper.SltAgreementInfoMapper;
import com.bonus.material.settlement.mapper.SltAgreementReduceMapper;
import com.bonus.material.task.domain.TmTask;
import com.bonus.material.task.mapper.TmTaskMapper;
import com.google.common.math.BigDecimalMath;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.bonus.common.log.annotation.SysLog;
import com.bonus.common.security.annotation.RequiresPermissions;
import com.bonus.material.settlement.domain.SltAgreementInfo;
import com.bonus.material.settlement.domain.dto.PeriodCostQueryDto;
import com.bonus.material.settlement.domain.vo.PeriodCostResultVo;
import com.bonus.material.settlement.domain.vo.PeriodCostSummaryVo;
import com.bonus.material.settlement.service.ISltAgreementInfoService;
import com.bonus.common.core.web.controller.BaseController;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.core.utils.poi.ExcelUtil;
import com.bonus.common.core.web.page.TableDataInfo;

import java.util.ArrayList;

/**
 * 结算信息Controller
 * 
 * @author xsheng
 * @date 2024-10-16
 */
@Api(tags = "结算信息接口")
@RestController
@RequestMapping("/slt_agreement_info")
@Slf4j
public class SltAgreementInfoController extends BaseController {

    @Autowired
    private ISltAgreementInfoService sltAgreementInfoService;

    @Autowired
    private SltAgreementInfoMapper sltAgreementInfoMapper;

    @Autowired
    private TmTaskMapper taskMapper;

    @Resource
    private SltAgreementReduceMapper sltAgreementRecudceMapper;

    /**
     * 查询结算信息列表
     */
    @ApiOperation(value = "查询结算信息列表")
    @RequiresPermissions("settlement:info:list")
    @GetMapping("/list")
    public TableDataInfo list(SltAgreementInfo sltAgreementInfo) {
        startPage();
        List<SltAgreementInfo> list = sltAgreementInfoService.selectSltAgreementInfoList(sltAgreementInfo);
        return getDataTable(list);
    }

    /**
     * 根据条件获取协议结算列表
     */
    @ApiOperation(value = "根据条件获取协议结算列表")
    @GetMapping("/getSltAgreementInfo4Project")
    public AjaxResult getSltAgreementInfo4Project(SltAgreementInfo bean) {
        Integer pageIndex = Convert.toInt(ServletUtils.getParameter("pageNum"), 1);
        Integer pageSize = Convert.toInt(ServletUtils.getParameter("pageSize"), 10);
        List<SltAgreementInfo> list = sltAgreementInfoService.getSltAgreementInfo4Project(bean);
        ListPagingUtil paginated = ListPagingUtil.paging(pageIndex, pageSize, list);
        // 新增外层计算-- 计算当前分页数据的各条目费用
        if (CollectionUtils.isNotEmpty(paginated.getRows())) {
            int loginUserHasSettlementPermission = sltAgreementInfoService.checkLoginUserHasSettlementPermission();
            for (Object row : paginated.getRows()) {
                if (row instanceof SltAgreementInfo) {
                    ((SltAgreementInfo) row).setSettlementType(loginUserHasSettlementPermission);

                }
                SltInfoVo sltInfoVo = null;
                if (row instanceof SltAgreementInfo) {
                    sltInfoVo = sltAgreementInfoService.getSltInfo((SltAgreementInfo) row);
                }
                if (sltInfoVo != null) {
                    list.get(list.indexOf(row)).setCosts(sltAgreementInfoService.sum(sltInfoVo.getLeaseCost(), sltInfoVo.getRepairCost(), sltInfoVo.getScrapCost(), sltInfoVo.getLoseCost()));
                    //((SltAgreementInfo) row).setCosts(sltAgreementInfoService.sum(sltInfoVo.getLeaseCost(), sltInfoVo.getRepairCost(), sltInfoVo.getScrapCost(), sltInfoVo.getLoseCost()));
                }
            }
            //ListPagingUtil resultPaging = ListPagingUtil.paging(pageIndex, pageSize, paginated.getRows());
            ListPagingUtil resultPaging = ListPagingUtil.paging(pageIndex, pageSize, list);
            resultPaging.setTotal(list.size());
            return AjaxResult.success(resultPaging);
        }

        return AjaxResult.success(ListPagingUtil.paging(pageIndex, pageSize, list));
    }



    @ApiOperation(value = "工程下拉选")
    @PostMapping("getProjectListByUnitIds")
    public AjaxResult getProjectListByUnitIds(@RequestBody BmProject bmProject) {
        return sltAgreementInfoService.getProjectListByUnitIds(bmProject);
    }


    @ApiOperation(value = "往来单位id和标段工程id获取协议信息")
    @PostMapping("getAgreementInfoById")
    public AjaxResult getAgreementInfoById(@RequestBody SelectDto dto){
        return sltAgreementInfoService.getAgreementInfoById(dto);
    }

    @ApiOperation(value = "根据协议获取结算清单")
    @PostMapping("/getSltInfo")
    public AjaxResult getSltInfo(@RequestBody List<SltAgreementInfo> list) {
        if (CollectionUtil.isEmpty(list)) {
            return AjaxResult.error("请选择协议");
        }
        if (list.get(0).getSettlementType() == null || list.get(0).getSettlementType() < 1) {
            int settlementType = sltAgreementInfoService.checkLoginUserHasSettlementPermission();
            // 设置结算权限
            list.forEach(info -> info.setSettlementType(settlementType));
        } else {
            list.forEach(info -> info.setSettlementType(list.get(0).getSettlementType()));
        }


        List<String> unitNames = new ArrayList<>();
        List<String> projectNames = new ArrayList<>();
        List<SltInfoVo> dataList = new ArrayList<>();
        SltInfoVo bean = new SltInfoVo();
        Long agreementId = null;
        for (SltAgreementInfo info : list) {
            unitNames.add(info.getUnitName());
            projectNames.add(info.getProjectName());
            SltInfoVo vo = sltAgreementInfoService.getSltInfo(info);
            if (vo == null) {
                vo = new SltInfoVo();
                vo.setLeaseCost(BigDecimal.ZERO);
                vo.setRepairCost(BigDecimal.ZERO);
                vo.setScrapCost(BigDecimal.ZERO);
                vo.setLoseCost(BigDecimal.ZERO);
                vo.setReductionCost(BigDecimal.ZERO);
                vo.setLeaseList(Collections.emptyList());
                vo.setRepairList(Collections.emptyList());
                vo.setScrapList(Collections.emptyList());
                vo.setLoseList(Collections.emptyList());
                vo.setReductionList(Collections.emptyList());
                vo.setRelations(Collections.emptyList());
            }
            dataList.add(vo);
            if (info.getAgreementId() != null) {
                agreementId = info.getAgreementId();
            }
        }
        bean = mergerData(bean, dataList,unitNames,projectNames);
        // 根据协议id获取申请时间
        TmTask tmTask = taskMapper.selectTaskById(agreementId, list.get(0).getSettlementType());
        if (tmTask != null) {
            bean.setApplyTime(tmTask.getCreateTime());
        }
        return AjaxResult.success(bean);
    }

    public SltInfoVo mergerData(SltInfoVo vo,List<SltInfoVo> list,List<String> unitNames,List<String> projectNames){
        vo.setUnitName(handleData(unitNames));
        vo.setProjectName(handleData(projectNames));
        BigDecimal leaseCost = BigDecimal.valueOf(0.00);
        BigDecimal repairCost = BigDecimal.valueOf(0.00);
        BigDecimal scrapCost = BigDecimal.valueOf(0.00);
        BigDecimal loseCost = BigDecimal.valueOf(0.00);
        BigDecimal reducCost = BigDecimal.valueOf(0.00);
        //租赁费用列表
        List<SltAgreementInfo> leaseList = new ArrayList<>();
        //维修费用列表
        List<SltAgreementInfo> repairList = new ArrayList<>();
        //报废费用列表
        List<SltAgreementInfo> scrapList = new ArrayList<>();
        //丢失费用列表
        List<SltAgreementInfo> loseList = new ArrayList<>();
        //减免费用列表
        List<SltAgreementReduce> reductionList = new ArrayList<>();
        List<SltAgreementRelation> relations = new ArrayList<>();
        for (SltInfoVo infoVo : list) {
            leaseCost = leaseCost.add(infoVo.getLeaseCost());
            repairCost = repairCost.add(infoVo.getRepairCost());
            scrapCost = scrapCost.add(infoVo.getScrapCost());
            loseCost = loseCost.add(infoVo.getLoseCost());
            reducCost = reducCost.add(infoVo.getReductionCost());
            leaseList.addAll(infoVo.getLeaseList());
            repairList.addAll(infoVo.getRepairList());
            scrapList.addAll(infoVo.getScrapList());
            loseList.addAll(infoVo.getLoseList());
            reductionList.addAll(infoVo.getReductionList());
            relations.addAll(infoVo.getRelations());
        }
        vo.setLeaseList(leaseList);
        vo.setRepairList(repairList);
        vo.setScrapList(scrapList);
        vo.setLoseList(loseList);
        vo.setReductionList(reductionList);
        vo.setLeaseCost(leaseCost);
        vo.setRepairCost(repairCost);
        vo.setScrapCost(scrapCost);
        vo.setLoseCost(loseCost);
        vo.setReductionCost(reducCost);
        vo.setRelations(relations);
        return vo;
    }

    public String handleData(List<String> list){
        StringBuilder sb = new StringBuilder();
        Set<String> set = new HashSet<>(list);
        for (String str : set) {
            sb.append(str).append("、");
        }
        return StringUtils.removeEnd(sb.toString(), "、");
    }

    @ApiOperation(value = "结算记录查询明细")
    @PostMapping("/getSltRecordDetailsList")
    public AjaxResult getSltRecordDetailsList(@RequestBody SltAgreementInfo info) {
        try {
            SltInfoVo bean = sltAgreementInfoService.getSltRecordDetailsList(info);
            return AjaxResult.success(bean);
        } catch (Exception e) {
            return AjaxResult.success(new SltInfoVo());
        }
    }

    /**
     * 获取结算审核列表
     */
    @ApiOperation(value = "获取结算审核列表")
    @GetMapping("/getSltExam")
    public TableDataInfo getSltExam(SltAgreementInfo bean) {
        startPage();
        List<SltAgreementApply> list = sltAgreementInfoService.getSltExam(bean);
        return getDataTable(list);
    }

    /**
     * 导出结算信息列表
     */
    @ApiOperation(value = "导出结算信息列表")
    @PreventRepeatSubmit
    @RequiresPermissions("settlement:info:export")
    @SysLog(title = "结算信息", businessType = OperaType.EXPORT, logType = 1,module = "仓储管理->导出结算信息")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SltAgreementInfo sltAgreementInfo) {
        List<SltAgreementInfo> list = sltAgreementInfoService.selectSltAgreementInfoList(sltAgreementInfo);
        ExcelUtil<SltAgreementInfo> util = new ExcelUtil<SltAgreementInfo>(SltAgreementInfo.class);
        util.exportExcel(response, list, "结算信息数据");
    }

    /**
     * 导出结算单
     * @param response
     * @param list
     * @param filename

     * @throws Exception
     */
    private void expOutExcel(HttpServletResponse response, List<SltLeaseInfo> list, String filename,String projectName,String unitName,BigDecimal totalCost,int type)
            throws Exception {
        if (list != null) {
            List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
            int size = list.size();
            for (int i = 0; i < size; i++) {
                SltLeaseInfo bean = list.get(i);
                Map<String, Object> maps = outReceiveDetailsBeanToMap(bean,type,0);
                results.add(maps);
            }
            List<String> headers = receiveDetailsHeader(type,0);
            HSSFWorkbook workbook = PoiOutPage.excelForcheckTwo(results, headers, filename,projectName,unitName,totalCost);
            OutputStream out = null;
            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
            response.addHeader("Content-Disposition",
                    "attachment;filename=" + URLEncoder.encode(filename, "UTF-8") + ".xls");
            response.setHeader("Pragma", "No-cache");
            out = response.getOutputStream();
            workbook.write(out);
            out.flush();
            out.close();
        }else{
            List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
            List<String> headers = receiveDetailsHeader(type,0);
            HSSFWorkbook workbook = PoiOutPage.excel(results, headers, filename);
            OutputStream out = null;
            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
            response.addHeader("Content-Disposition",
                    "attachment;filename=" + URLEncoder.encode(filename, "UTF-8") + ".xls");
            response.setHeader("Pragma", "No-cache");
            out = response.getOutputStream();
            workbook.write(out);
            out.flush();
            out.close();
        }
    }


    /**
     * 导出结算单--all
     * @throws Exception
     */
    private void expOutExcelAll(HttpServletResponse response, List<SltLeaseInfo> lease,List<SltLeaseInfo> lose,List<SltLeaseInfo> repair,List<SltLeaseInfo> scrap,List<SltLeaseInfo> reduction,
                                String filename,String projectName,String unitName,BigDecimal totalCostLease,BigDecimal totalCostLose,BigDecimal totalCostRepair,BigDecimal totalCostScrap,BigDecimal totalCostReduction)
            throws Exception {
        List<Map<String, Object>> resultsLease = new ArrayList<Map<String, Object>>();
        List<Map<String, Object>> resultsLose = new ArrayList<Map<String, Object>>();
        List<Map<String, Object>> resultsRepair = new ArrayList<Map<String, Object>>();
        List<Map<String, Object>> resultsScrap = new ArrayList<Map<String, Object>>();
        List<Map<String, Object>> resultsReduction = new ArrayList<Map<String, Object>>();
        if (lease!= null) {
            int sizeLease = lease.size();
            for (int i = 0; i < sizeLease; i++) {
                SltLeaseInfo bean = lease.get(i);
                Map<String, Object> maps = outReceiveDetailsBeanToMap(bean,1,1);
                resultsLease.add(maps);
            }
        }
        if (lose!= null) {
            int sizeLose = lose.size();
            for (int i = 0; i < sizeLose; i++) {
                SltLeaseInfo bean = lose.get(i);
                Map<String, Object> maps = outReceiveDetailsBeanToMap(bean,2,1);
                resultsLose.add(maps);
            }
        }
        if (repair!= null) {
            int sizeRepair = repair.size();
            for (int i = 0; i < sizeRepair; i++) {
                SltLeaseInfo bean = repair.get(i);
                Map<String, Object> maps = outReceiveDetailsBeanToMap(bean,3,1);
                resultsRepair.add(maps);
            }
        }
        if (scrap!= null) {
            int sizeScrap = scrap.size();
            for (int i = 0; i < sizeScrap; i++) {
                SltLeaseInfo bean = scrap.get(i);
                Map<String, Object> maps = outReceiveDetailsBeanToMap(bean,4,1);
                resultsScrap.add(maps);
            }
        }
        if (reduction!= null) {
            int sizeReduction = reduction.size();
            for (int i = 0; i < sizeReduction; i++) {
                SltLeaseInfo bean = reduction.get(i);
                Map<String, Object> maps = outReceiveDetailsBeanToMap(bean,5,1);
                resultsReduction.add(maps);
            }
        }


        List<String> headersLease = receiveDetailsHeader(1,1);
        List<String> headersLose = receiveDetailsHeader(2,1);
        List<String> headersRepair = receiveDetailsHeader(3,1);
        List<String> headersScrap = receiveDetailsHeader(4,1);
        List<String> headersReduction = receiveDetailsHeader(5,1);
        HSSFWorkbook workbook = PoiOutPage.excelForcheckAll(resultsLease,resultsLose,resultsRepair,resultsScrap,resultsReduction, headersLease,headersLose,headersRepair,headersScrap,headersReduction, filename,projectName,unitName,totalCostLease,totalCostLose,totalCostRepair,totalCostScrap,totalCostReduction);
        OutputStream out = null;
        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
        response.addHeader("Content-Disposition",
                "attachment;filename=" + URLEncoder.encode(filename, "UTF-8") + ".xls");
        response.setHeader("Pragma", "No-cache");
        out = response.getOutputStream();
        workbook.write(out);
        out.flush();
        out.close();

    }


    /**
     * 结算记录查询--导出全部明细
     */
    private void expOutExcelAlls(HttpServletResponse response, List<SltLeaseInfo> lease,List<SltLeaseInfo> lose,List<SltLeaseInfo> repair,List<SltLeaseInfo> scrap,List<SltLeaseInfo> reduction,
                                String filename,String projectName,String unitName,BigDecimal totalCostLease,BigDecimal totalCostLose,BigDecimal totalCostRepair,BigDecimal totalCostScrap,BigDecimal totalCostReduction)
            throws Exception {
        List<Map<String, Object>> resultsLease = new ArrayList<Map<String, Object>>();
        List<Map<String, Object>> resultsLose = new ArrayList<Map<String, Object>>();
        List<Map<String, Object>> resultsRepair = new ArrayList<Map<String, Object>>();
        List<Map<String, Object>> resultsScrap = new ArrayList<Map<String, Object>>();
        List<Map<String, Object>> resultsReduction = new ArrayList<Map<String, Object>>();

        if (lease!= null) {
            int sizeLease = lease.size();
            for (int i = 0; i < sizeLease; i++) {
                SltLeaseInfo bean = lease.get(i);
                Map<String, Object> maps = outReceiveDetailsBeanToMap(bean,1,1);
                resultsLease.add(maps);
            }
        }
        if (lose!= null) {
            int sizeLose = lose.size();
            for (int i = 0; i < sizeLose; i++) {
                SltLeaseInfo bean = lose.get(i);
                Map<String, Object> maps = outReceiveDetailsBeanToMap(bean,2,1);
                resultsLose.add(maps);
            }
        }
        if (repair!= null) {
            int sizeRepair = repair.size();
            for (int i = 0; i < sizeRepair; i++) {
                SltLeaseInfo bean = repair.get(i);
                Map<String, Object> maps = outReceiveDetailsBeanToMap(bean,3,1);
                resultsRepair.add(maps);
            }
        }
        if (scrap!= null) {
            int sizeScrap = scrap.size();
            for (int i = 0; i < sizeScrap; i++) {
                SltLeaseInfo bean = scrap.get(i);
                Map<String, Object> maps = outReceiveDetailsBeanToMap(bean,4,1);
                resultsScrap.add(maps);
            }
        }

        if (reduction!= null) {
            int sizeReduction = reduction.size();
            for (int i = 0; i < sizeReduction; i++) {
                SltLeaseInfo bean = reduction.get(i);
                Map<String, Object> maps = outReceiveDetailsBeanToMap(bean,5,1);
                resultsReduction.add(maps);
            }
        }

        List<String> headersLease = receiveDetailsHeader(1,1);
        List<String> headersLose = receiveDetailsHeader(2,1);
        List<String> headersRepair = receiveDetailsHeader(3,1);
        List<String> headersScrap = receiveDetailsHeader(4,1);
        List<String> headersReduction = receiveDetailsHeader(5,1);
        HSSFWorkbook workbook = PoiOutPage.excelForcheckAlls(resultsLease,resultsLose,resultsRepair,resultsScrap,resultsReduction, headersLease,headersLose,headersRepair,headersScrap,headersReduction, filename,projectName,unitName,totalCostLease,totalCostLose,totalCostRepair,totalCostScrap,totalCostReduction);
        OutputStream out = null;
        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
        response.addHeader("Content-Disposition",
                "attachment;filename=" + URLEncoder.encode(filename, "UTF-8") + ".xls");
        response.setHeader("Pragma", "No-cache");
        out = response.getOutputStream();
        workbook.write(out);
        out.flush();
        out.close();

    }

    /**
     * 租赁费用单数据转换
     * @param bean
     * @return
     */
    private Map<String, Object> outReceiveDetailsBeanToMap(SltLeaseInfo bean,int type,int flag) {
        // 创建一个SimpleDateFormat对象，定义日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Map<String, Object> maps = new LinkedHashMap<String, Object>();
        if(type==1){
//            maps.put("unitName", bean.getUnitName());
//            maps.put("projectName", bean.getProjectName());
            if (flag==0){
                maps.put("typeName", bean.getTypeName());
                maps.put("modelName", bean.getModelName());
                maps.put("mtUnitName", bean.getMtUnitName());
                maps.put("leasePrice", bean.getLeasePrice());
                maps.put("num", bean.getNum());
                maps.put("startTime", bean.getStartTime()==null ? null:dateFormat.format(bean.getStartTime()));
                maps.put("endTime", bean.getEndTime()==null ? null:dateFormat.format(bean.getEndTime()));
                maps.put("leaseDays", bean.getLeaseDays());
                maps.put("costs", bean.getCosts().setScale(2, RoundingMode.HALF_UP));
            }else {
                maps.put("typeName", bean.getTypeName());
                maps.put("modelName", bean.getModelName());
                maps.put("mtUnitName", bean.getMtUnitName());
                maps.put("leasePrice", bean.getLeasePrice());
                maps.put("num", bean.getNum());
                maps.put("startTime", bean.getStartTime()==null ? null:dateFormat.format(bean.getStartTime()));
                maps.put("endTime", bean.getEndTime()==null ? null:dateFormat.format(bean.getEndTime()));
                maps.put("leaseDays", bean.getLeaseDays());
                maps.put("costs", bean.getCosts().setScale(2, RoundingMode.HALF_UP));
                maps.put("t1", "");
            }
        }else if(type==2) {
            if(flag==0){
                maps.put("typeName", bean.getTypeName());
                maps.put("modelName", bean.getModelName());
                maps.put("mtUnitName", bean.getMtUnitName());
                maps.put("num", bean.getNum());
                maps.put("costs", bean.getCosts());
            }else{
                maps.put("typeName", bean.getTypeName());
                maps.put("modelName", bean.getModelName());
                maps.put("mtUnitName", bean.getMtUnitName());
                maps.put("num", bean.getNum());
                maps.put("costs", bean.getCosts());
                maps.put("t1", "");
                maps.put("t2", "");
                maps.put("t3", "");
                maps.put("t4", "");
                maps.put("t5", "");
            }
        }else if(type==3){
            if(flag==0){
                maps.put("typeName", bean.getTypeName());
                maps.put("modelName", bean.getModelName());
                maps.put("mtUnitName", bean.getMtUnitName());
                maps.put("num", bean.getNum());
                maps.put("partType", bean.getPartType());
                maps.put("costs", bean.getCosts());
            }else{
            maps.put("typeName", bean.getTypeName());
            maps.put("modelName", bean.getModelName());
            maps.put("mtUnitName", bean.getMtUnitName());
            maps.put("num", bean.getNum());
            maps.put("partType", bean.getPartType());
            maps.put("costs", bean.getCosts());
            maps.put("t1", "");
            maps.put("t2", "");
            maps.put("t3", "");
            maps.put("t4", "");
            }
        }else if(type==4){
                if(flag==0){
                    maps.put("typeName", bean.getTypeName());
                    maps.put("modelName", bean.getModelName());
                    maps.put("mtUnitName", bean.getMtUnitName());
                    maps.put("num", bean.getNum());
                    maps.put("partType", bean.getPartType());
                    maps.put("costs", bean.getCosts());
                }else{
                    maps.put("typeName", bean.getTypeName());
                    maps.put("modelName", bean.getModelName());
                    maps.put("mtUnitName", bean.getMtUnitName());
                    maps.put("num", bean.getNum());
                    maps.put("partType", bean.getPartType());
                    maps.put("costs", bean.getCosts());
                    maps.put("t1", "");
                    maps.put("t2", "");
                    maps.put("t3", "");
                    maps.put("t4", "");
                }
            } else if(type==5){
            maps.put("typeName", bean.getTypeName());
            maps.put("modelName", bean.getModelName());
            maps.put("mtUnitName", bean.getUnitName());
            maps.put("leasePrice", bean.getLeasePrice());
            maps.put("num", bean.getReduceNum());
            maps.put("startTime", bean.getStartTime()==null ? null:dateFormat.format(bean.getStartTime()));
            maps.put("endTime", bean.getEndTime()==null ? null:dateFormat.format(bean.getEndTime()));
            maps.put("leaseDays", bean.getDays());
            maps.put("remark", bean.getRemark());
            maps.put("costs", bean.getLeaseMoney().setScale(2, RoundingMode.HALF_UP));
        }
        return maps;
    }

    /**
     * 租赁费用单表头
     * @return
     */
    private List<String> receiveDetailsHeader(int type,int flag) {
        ArrayList<String> list = new ArrayList<String>();
        if(type==1){
//            list.add("结算单位");
//            list.add("结算工程");

            if (flag==0){
                list.add("设备名称");
                list.add("规格型号");
                list.add("计量单位");
                list.add("租赁单价");
                list.add("租赁数量");
                list.add("租赁日期");
                list.add("归还日期");
                list.add("租赁天数");
                list.add("租赁费用（元）");
            }else {
                list.add("设备名称");
                list.add("规格型号");
                list.add("计量单位");
                list.add("租赁单价");
                list.add("租赁数量");
                list.add("租赁日期");
                list.add("归还日期");
                list.add("租赁天数");
                list.add("租赁费用（元）");
                list.add(" ");
            }
        }else if(type==2){
            if(flag==0){
                list.add("设备名称");
                list.add("规格型号");
                list.add("计量单位");
                list.add("丢失数量");
                list.add("丢失费用（元）");
            }else{
                list.add("设备名称");
                list.add("规格型号");
                list.add("计量单位");
                list.add("丢失数量");
                list.add("丢失费用（元）");
                list.add(" ");
                list.add(" ");
                list.add(" ");
                list.add(" ");
                list.add(" ");
            }

        }else if(type==3){
            if(flag==0){
                list.add("设备名称");
                list.add("规格型号");
                list.add("计量单位");
                list.add("维修数量");
                list.add("是否收费");
                list.add("维修费用（元）");
            }else{
                list.add("设备名称");
                list.add("规格型号");
                list.add("计量单位");
                list.add("维修数量");
                list.add("是否收费");
                list.add("维修费用（元）");
                list.add("");
                list.add("");
                list.add("");
                list.add(" ");
            }
        }else if(type==4){
            if(flag==0){
                list.add("设备名称");
                list.add("规格型号");
                list.add("计量单位");
                list.add("报废数量");
                list.add("是否收费");
                list.add("报废费用（元）");
            }else{
                list.add("设备名称");
                list.add("规格型号");
                list.add("计量单位");
                list.add("报废数量");
                list.add("是否收费");
                list.add("报废费用（元）");
                list.add("");
                list.add("");
                list.add("");
                list.add(" ");
            }
        }else if (type==5){
            list.add("设备名称");
            list.add("规格型号");
            list.add("单位");
            list.add("租赁单价");
            list.add("减免数量");
            list.add("减免开始日期");
            list.add("减免结束日期");
            list.add("减免天数");
            list.add("减免原因");
            list.add("减免费用（元）");
        }
        return list;
    }

    /**
     * 导出租赁明细
     */
    @ApiOperation(value = "导出结算信息列表")
    @PreventRepeatSubmit
//    @RequiresPermissions("settlement:info:export")
    @SysLog(title = "结算信息", businessType = OperaType.EXPORT, logType = 1,module = "仓储管理->导出租赁明细")
    @PostMapping("/exportLease")
    public void exportLease(HttpServletResponse response, @RequestParam("params") String params) {
        try {
            List<SltAgreementInfo> sltAgreementInfo = JSONObject.parseArray(params,SltAgreementInfo.class);
            List<String> projectNames = new ArrayList<>();
            List<String> unitNames = new ArrayList<>();
            List<SltAgreementInfo> leaseList = new ArrayList<>();
            String fileName = "租赁费用明细表";
            for (SltAgreementInfo info : sltAgreementInfo) {
                projectNames.add(info.getProjectName());
                unitNames.add(info.getUnitName());
                List<SltAgreementInfo> oneOfList = sltAgreementInfoMapper.getLeaseList(info);
                leaseList.addAll(oneOfList);
            }
            String projectName = handleData(projectNames);
            String unitName = handleData(unitNames);
            BigDecimal totalCost = BigDecimal.valueOf(0.00);
            for (SltAgreementInfo bean : leaseList) {
                if (null == bean.getLeasePrice()) {
                    bean.setLeasePrice(BigDecimal.valueOf(0.00));
                }else{
                    bean.setLeasePrice(bean.getLeasePrice().setScale(2, BigDecimal.ROUND_HALF_UP));
                }

                if (null == bean.getNum()) {
                    bean.setNum(BigDecimal.valueOf(0L));
                }
                if (null == bean.getLeaseDays()) {
                    bean.setLeaseDay(0L);
                }
                BigDecimal leasePrice = bean.getLeasePrice();
                BigDecimal num = bean.getNum();
                BigDecimal leaseDays = new BigDecimal(bean.getLeaseDays());
                BigDecimal costs = leasePrice.multiply(num).multiply(leaseDays).setScale(2, BigDecimal.ROUND_HALF_UP);
                if(costs!=null){
                    totalCost = totalCost.add(costs);
                }
                bean.setCosts(costs);
            }
            List<SltLeaseInfo> lease = Convert.toList(SltLeaseInfo.class, leaseList);
            expOutExcel(response,lease,fileName,projectName,unitName,totalCost,1);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
    }

    /**
     * 导出丢失费用明细
     */
    @ApiOperation(value = "导出结算信息列表")
    @PreventRepeatSubmit
//    @RequiresPermissions("settlement:info:export")
    @SysLog(title = "结算信息", businessType = OperaType.EXPORT, logType = 1,module = "仓储管理->导出丢失费用明细")
    @PostMapping("/exportLose")
    public void exportLose(HttpServletResponse response, @RequestParam("params") String params) {
        try {
            String fileName = "丢失费用明细表";
            List<SltAgreementInfo> sltAgreementInfo = JSONObject.parseArray(params,SltAgreementInfo.class);
            List<String> projectNames = new ArrayList<>();
            List<String> unitNames = new ArrayList<>();
            List<SltAgreementInfo> loseList = new ArrayList<>();
            for (SltAgreementInfo info : sltAgreementInfo) {
                projectNames.add(info.getProjectName());
                unitNames.add(info.getUnitName());
                List<SltAgreementInfo> oneOfList = sltAgreementInfoMapper.getLoseList(info);
                loseList.addAll(oneOfList);
            }
            String projectName = handleData(projectNames);
            String unitName = handleData(unitNames);
            BigDecimal totalCost = BigDecimal.valueOf(0.00);
            for (SltAgreementInfo bean : loseList) {
                if (null == bean.getBuyPrice()) {
                    bean.setBuyPrice(BigDecimal.valueOf(0.00));
                }
                if (null == bean.getNum()) {
                    bean.setNum(BigDecimal.valueOf(0L));
                }
                BigDecimal buyPrice = bean.getBuyPrice();
                BigDecimal num = bean.getNum();
                // 原价 x 数量
                BigDecimal costs = buyPrice.multiply(num);
                if(costs!=null){
                    totalCost = totalCost.add(costs);
                }
                //计算租赁费用
                bean.setCosts(costs);
            }
            List<SltLeaseInfo> lose = Convert.toList(SltLeaseInfo.class, loseList);
            expOutExcel(response,lose,fileName,projectName,unitName,totalCost,2);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
    }

    /**
     * 导出维修费用明细
     */
    @ApiOperation(value = "导出结算信息列表")
    @PreventRepeatSubmit
//    @RequiresPermissions("settlement:info:export")
    @SysLog(title = "结算信息", businessType = OperaType.EXPORT, logType = 1,module = "仓储管理->导出维修费用明细")
    @PostMapping("/exportRepair")
    public void exportRepair(HttpServletResponse response, @RequestParam("params") String params) {
        try {

            String fileName = "维修费用明细表";
            List<SltAgreementInfo> sltAgreementInfo = JSONObject.parseArray(params,SltAgreementInfo.class);
            List<String> projectNames = new ArrayList<>();
            List<String> unitNames = new ArrayList<>();
            BigDecimal totalCost = BigDecimal.valueOf(0.00);
            List<SltAgreementInfo> repairList = new ArrayList<>();
            for (SltAgreementInfo info : sltAgreementInfo) {
                projectNames.add(info.getProjectName());
                unitNames.add(info.getUnitName());
                List<TmTask> taskList = taskMapper.getTaskIdList(info);
                if (null != taskList && !taskList.isEmpty()) {
                    List<SltAgreementInfo> repairDetailsList = sltAgreementInfoMapper.getRepairDetailsList(info, taskList);
                    repairList.addAll(repairDetailsList);
                }
            }
//            List<TmTask> taskList = taskMapper.getTaskIdList(sltAgreementInfo);
//            if (null != taskList && !taskList.isEmpty()) {
//                List<SltAgreementInfo> repairDetailsList = sltAgreementInfoMapper.getRepairDetailsList(taskList);
//                repairList.addAll(repairDetailsList);
//            }
            for (SltAgreementInfo bean : repairList) {
                if (bean.getCosts()!=null && (bean.getPartType().equals("收费"))) {
                    totalCost = totalCost.add(bean.getCosts());
                }
            }
            String projectName = handleData(projectNames);
            String unitName = handleData(unitNames);
            List<SltLeaseInfo> repair = Convert.toList(SltLeaseInfo.class, repairList);
            expOutExcel(response,repair,fileName,projectName,unitName,totalCost,3);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
    }

    /**
     * 导出减免费用明细
     */
    @ApiOperation(value = "导出减免费用明细")
    @PreventRepeatSubmit
//    @RequiresPermissions("settlement:info:export")
    @SysLog(title = "结算信息", businessType = OperaType.EXPORT, logType = 1,module = "仓储管理->导出减免费用明细")
    @PostMapping("/exportReduction")
    public void exportReduction(HttpServletResponse response, @RequestParam("params") String params) {
        try {
            String fileName = "减免费用明细表";
            List<SltAgreementInfo> sltAgreementInfo = JSONObject.parseArray(params,SltAgreementInfo.class);
            List<String> projectNames = new ArrayList<>();
            List<String> unitNames = new ArrayList<>();
            BigDecimal reductionCost = BigDecimal.valueOf(0.00);
            List<SltAgreementReduce> reductionList = new ArrayList<>();
            for (SltAgreementInfo info : sltAgreementInfo) {
                projectNames.add(info.getProjectName());
                unitNames.add(info.getUnitName());
                if (info.getAgreementId() != null){
                    SltAgreementReduce bean =new SltAgreementReduce();
                    bean.setAgreementId(info.getAgreementId());
                    List<SltAgreementReduce> oneOfList = sltAgreementRecudceMapper.getReductionList(bean);
                    reductionList.addAll(oneOfList);
                }

            }
//            if (sltAgreementInfo.getAgreementId() != null){
//                SltAgreementReduce bean =new SltAgreementReduce();
//                bean.setAgreementId(sltAgreementInfo.getAgreementId());
//                reductionList = sltAgreementRecudceMapper.getReductionList(bean);
//            }
            for (SltAgreementReduce reduction : reductionList) {
                if(reduction.getLeaseMoney()!=null){
                    reductionCost = reductionCost.add(reduction.getLeaseMoney());
                }
            }
            String projectName = handleData(projectNames);
            String unitName = handleData(unitNames);
            List<SltLeaseInfo> repair = Convert.toList(SltLeaseInfo.class, reductionList);
            expOutExcel(response,repair,fileName,projectName,unitName,reductionCost,5);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
    }

    /**
     * 导出报废费用明细
     */
    @ApiOperation(value = "导出结算信息列表")
    @PreventRepeatSubmit
//    @RequiresPermissions("settlement:info:export")
    @SysLog(title = "报废信息", businessType = OperaType.EXPORT, logType = 1,module = "仓储管理->导出报废费用明细")
    @PostMapping("/exportScrap")
    public void exportScrap(HttpServletResponse response, @RequestParam("params") String params) {
        try {
            String fileName = "报废费用明细表";
            List<SltAgreementInfo> sltAgreementInfo = JSONObject.parseArray(params,SltAgreementInfo.class);
            List<String> projectNames = new ArrayList<>();
            List<String> unitNames = new ArrayList<>();
            BigDecimal totalCost = BigDecimal.valueOf(0.00);

            List<SltAgreementInfo> scrapList = new ArrayList<>();
            for (SltAgreementInfo info : sltAgreementInfo) {
                projectNames.add(info.getProjectName());
                unitNames.add(info.getUnitName());
                List<TmTask> taskList = taskMapper.getTaskIdList(info);
                if (null != taskList && !taskList.isEmpty()) {
                    List<SltAgreementInfo> scrapDetailsList = sltAgreementInfoMapper.getScrapDetailsList(info, taskList);
                    scrapList.addAll(scrapDetailsList);
                }
            }

//            List<TmTask> taskList = taskMapper.getTaskIdList(sltAgreementInfo);
//            if (null != taskList && !taskList.isEmpty()) {
//                List<SltAgreementInfo> scrapDetailsList = sltAgreementInfoMapper.getScrapDetailsList(taskList);
//                scrapList.addAll(scrapDetailsList);
//            }
            for (SltAgreementInfo bean : scrapList) {
                if (bean.getCosts()!=null && (bean.getPartType().equals("收费"))) {
                    totalCost = totalCost.add(bean.getCosts());
                }
            }
            String projectName = handleData(projectNames);
            String unitName = handleData(unitNames);
            List<SltLeaseInfo> scrap = Convert.toList(SltLeaseInfo.class, scrapList);
            expOutExcel(response,scrap,fileName,projectName,unitName,totalCost,4);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
    }

    /**
     * 获取结算信息详细信息
     */
    @ApiOperation(value = "获取结算信息详细信息")
    @RequiresPermissions("settlement:info:query")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(sltAgreementInfoService.selectSltAgreementInfoById(id));
    }

    /**
     * 新增结算信息
     */
    @ApiOperation(value = "新增结算信息")
    @PreventRepeatSubmit
    @RequiresPermissions("settlement:info:add")
    @SysLog(title = "结算信息", businessType = OperaType.INSERT, logType = 1,module = "仓储管理->新增结算信息")
    @PostMapping
    public AjaxResult add(@RequestBody SltAgreementInfo sltAgreementInfo) {
        try {
            return toAjax(sltAgreementInfoService.insertSltAgreementInfo(sltAgreementInfo));
        } catch (Exception e) {
            return error("系统错误, " + e.getMessage());
        }
    }


    /**
     * 各明细导出--all
     */
    @ApiOperation(value = "各明细导出")
    @PreventRepeatSubmit
//    @RequiresPermissions("settlement:info:export")
    @SysLog(title = "结算信息", businessType = OperaType.EXPORT, logType = 1,module = "仓储管理->各明细导出")
    @PostMapping("/exportEach")
    public void exportEach(HttpServletResponse response, @RequestParam("params") String params) {
        try {
            String fileName = "结算费用明细";
            List<SltAgreementInfo> sltAgreementInfo = JSONObject.parseArray(params,SltAgreementInfo.class);
//            List<String> projectNames = new ArrayList<>();
//            List<String> unitNames = new ArrayList<>();
            // 创建工作簿
            HSSFWorkbook workbook = new HSSFWorkbook();
            int sheetIndex = 1;
            for (SltAgreementInfo info : sltAgreementInfo) {
                // 创建工作表
                HSSFSheet sheet = workbook.createSheet("sheet" + sheetIndex);
                // 处理单个info的导出逻辑
                List<String> projectNames = new ArrayList<>();
                List<String> unitNames = new ArrayList<>();
                projectNames.add(info.getProjectName());
                unitNames.add(info.getUnitName());
                //租赁费用明细
                BigDecimal totalCostLease = BigDecimal.valueOf(0.00);
                List<SltAgreementInfo> leaseList = new ArrayList<>();
                List<SltAgreementInfo> oneOfList = sltAgreementInfoMapper.getLeaseList(info);
                leaseList.addAll(oneOfList);
                for (SltAgreementInfo bean : leaseList) {
                    if (null == bean.getLeasePrice()) {
                        bean.setLeasePrice(BigDecimal.valueOf(0.00));
                    }
                    if (null == bean.getNum()) {
                        bean.setNum(BigDecimal.valueOf(0L));
                    }
                    if (null == bean.getLeaseDays()) {
                        bean.setLeaseDay(0L);
                    }
                    BigDecimal leasePrice = bean.getLeasePrice();
                    BigDecimal num = bean.getNum();
                    BigDecimal leaseDays = new BigDecimal(bean.getLeaseDays());
                    BigDecimal costs = leasePrice.multiply(num).multiply(leaseDays);
                    if(costs!=null){
                        totalCostLease = totalCostLease.add(costs);
                    }
                    bean.setCosts(costs);
                }
                List<SltLeaseInfo> lease = Convert.toList(SltLeaseInfo.class, leaseList);

                //丢失费用明细
                BigDecimal totalCostLose = BigDecimal.valueOf(0.00);
                List<SltAgreementInfo> loseList = new ArrayList<>();
                List<SltAgreementInfo> oneOfListLose = sltAgreementInfoMapper.getLoseList(info);
                loseList.addAll(oneOfListLose);
                for (SltAgreementInfo bean : loseList) {
                    if (null == bean.getBuyPrice()) {
                        bean.setBuyPrice(BigDecimal.valueOf(0.00));
                    }
                    if (null == bean.getNum()) {
                        bean.setNum(BigDecimal.valueOf(0L));
                    }
                    BigDecimal buyPrice = bean.getBuyPrice();
                    BigDecimal num = bean.getNum();
                    // 原价 x 数量
                    BigDecimal costs = buyPrice.multiply(num);
                    if(costs!=null){
                        totalCostLose = totalCostLose.add(costs);
                    }
                    //计算租赁费用
                    bean.setCosts(costs);
                }
                List<SltLeaseInfo> lose = Convert.toList(SltLeaseInfo.class, loseList);


                //维修费用明细
                BigDecimal totalCostRepair = BigDecimal.valueOf(0.00);
                List<SltAgreementInfo> repairList = new ArrayList<>();
                List<TmTask> taskList = taskMapper.getTaskIdList(info);
                if (null != taskList && !taskList.isEmpty()) {
                    List<SltAgreementInfo> repairDetailsList = sltAgreementInfoMapper.getRepairDetailsList(info, taskList);
                    repairList.addAll(repairDetailsList);
                }
                for (SltAgreementInfo bean : repairList) {
                    if (bean.getCosts()!=null && (bean.getPartType().equals("收费"))) {
                        totalCostRepair = totalCostRepair.add(bean.getCosts());
                    }
                }
                List<SltLeaseInfo> repair = Convert.toList(SltLeaseInfo.class, repairList);


                //报废费用明细
                BigDecimal totalCostScrap = BigDecimal.valueOf(0.00);
                List<SltAgreementInfo> scrapList = new ArrayList<>();
                List<TmTask> taskListScrap = taskMapper.getTaskIdList(info);
                if (null != taskListScrap && !taskListScrap.isEmpty()) {
                    List<SltAgreementInfo> scrapDetailsList = sltAgreementInfoMapper.getScrapDetailsList(info, taskListScrap);
                    scrapList.addAll(scrapDetailsList);
                }
                for (SltAgreementInfo bean : scrapList) {
                    if (bean.getCosts()!=null && (bean.getPartType().equals("收费"))) {
                        totalCostScrap = totalCostScrap.add(bean.getCosts());
                    }
                }
                List<SltLeaseInfo> scrap = Convert.toList(SltLeaseInfo.class, scrapList);


                //减免费用明细
                BigDecimal totalCostReduction = BigDecimal.valueOf(0.00);
                List<SltAgreementReduce> reductionList = new ArrayList<>();

                if (info.getAgreementId() != null){
                    SltAgreementReduce bean =new SltAgreementReduce();
                    bean.setAgreementId(info.getAgreementId());
                    List<SltAgreementReduce> oneOfListReduction = sltAgreementRecudceMapper.getReductionList(bean);
                    reductionList.addAll(oneOfListReduction);
                }
                for (SltAgreementReduce reduction : reductionList) {
                    if(reduction.getLeaseMoney()!=null){
                        totalCostReduction = totalCostReduction.add(reduction.getLeaseMoney());
                    }
                }
                List<SltLeaseInfo> reduction = Convert.toList(SltLeaseInfo.class, reductionList);
                String projectName = handleData(projectNames);
                String unitName = handleData(unitNames);

                List<Map<String, Object>> resultsLease = new ArrayList<Map<String, Object>>();
                List<Map<String, Object>> resultsLose = new ArrayList<Map<String, Object>>();
                List<Map<String, Object>> resultsRepair = new ArrayList<Map<String, Object>>();
                List<Map<String, Object>> resultsScrap = new ArrayList<Map<String, Object>>();
                List<Map<String, Object>> resultsReduction = new ArrayList<Map<String, Object>>();
                if (lease!= null) {
                    int sizeLease = lease.size();
                    for (int i = 0; i < sizeLease; i++) {
                        SltLeaseInfo bean = lease.get(i);
                        Map<String, Object> maps = outReceiveDetailsBeanToMap(bean,1,1);
                        resultsLease.add(maps);
                    }
                }
                if (lose!= null) {
                    int sizeLose = lose.size();
                    for (int i = 0; i < sizeLose; i++) {
                        SltLeaseInfo bean = lose.get(i);
                        Map<String, Object> maps = outReceiveDetailsBeanToMap(bean,2,1);
                        resultsLose.add(maps);
                    }
                }
                if (repair!= null) {
                    int sizeRepair = repair.size();
                    for (int i = 0; i < sizeRepair; i++) {
                        SltLeaseInfo bean = repair.get(i);
                        Map<String, Object> maps = outReceiveDetailsBeanToMap(bean,3,1);
                        resultsRepair.add(maps);
                    }
                }
                if (scrap!= null) {
                    int sizeScrap = scrap.size();
                    for (int i = 0; i < sizeScrap; i++) {
                        SltLeaseInfo bean = scrap.get(i);
                        Map<String, Object> maps = outReceiveDetailsBeanToMap(bean,4,1);
                        resultsScrap.add(maps);
                    }
                }
                if (reduction!= null) {
                    int sizeReduction = reduction.size();
                    for (int i = 0; i < sizeReduction; i++) {
                        SltLeaseInfo bean = reduction.get(i);
                        Map<String, Object> maps = outReceiveDetailsBeanToMap(bean,5,1);
                        resultsReduction.add(maps);
                    }
                }


                List<String> headersLease = receiveDetailsHeader(1,1);
                List<String> headersLose = receiveDetailsHeader(2,1);
                List<String> headersRepair = receiveDetailsHeader(3,1);
                List<String> headersScrap = receiveDetailsHeader(4,1);
                List<String> headersReduction = receiveDetailsHeader(5,1);
                // 创建工作簿和工作表
                PoiOutPage.excelForcheckEach(workbook, sheet, resultsLease,resultsLose,resultsRepair,resultsScrap,resultsReduction, headersLease,headersLose,headersRepair,headersScrap,headersReduction,projectName,unitName,totalCostLease,totalCostLose,totalCostRepair,totalCostScrap,totalCostReduction);


             //   expOutExcelAll(response,lease,lose,repair,scrap,reduction,fileName,projectName,unitName,totalCostLease,totalCostLose,totalCostRepair,totalCostScrap,totalCostReduction);
                sheetIndex++;
            }
            OutputStream out = null;
            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
            response.addHeader("Content-Disposition",
                    "attachment;filename=" + URLEncoder.encode("各结算明细", "UTF-8") + ".xls");
            response.setHeader("Pragma", "No-cache");
            out = response.getOutputStream();
            workbook.write(out);
            out.flush();
            out.close();

        } catch (Exception e) {
            log.error(e.toString(), e);
        }
    }

    /**
     * 导出结算信息列表--all
     */
    @ApiOperation(value = "导出结算信息列表")
    @PreventRepeatSubmit
//    @RequiresPermissions("settlement:info:export")
    @SysLog(title = "结算信息", businessType = OperaType.EXPORT, logType = 1,module = "仓储管理->导出租赁明细")
    @PostMapping("/exportAll")
    public void exportAll(HttpServletResponse response, @RequestParam("params") String params) {
        try {
                String fileName = "结算费用明细";
                List<SltAgreementInfo> sltAgreementInfo = JSONObject.parseArray(params,SltAgreementInfo.class);
                List<String> projectNames = new ArrayList<>();
                List<String> unitNames = new ArrayList<>();
//            String projectName = sltAgreementInfo.getProjectName();
//            String unitName = sltAgreementInfo.getUnitName();

                //租赁费用明细
                BigDecimal totalCostLease = BigDecimal.valueOf(0.00);
                List<SltAgreementInfo> leaseList = new ArrayList<>();
                for (SltAgreementInfo info : sltAgreementInfo) {
                    projectNames.add(info.getProjectName());
                    unitNames.add(info.getUnitName());
                    List<SltAgreementInfo> oneOfList = sltAgreementInfoMapper.getLeaseList(info);
                    leaseList.addAll(oneOfList);
                }
                for (SltAgreementInfo bean : leaseList) {
                    if (null == bean.getLeasePrice()) {
                        bean.setLeasePrice(BigDecimal.valueOf(0.00));
                    }
                    if (null == bean.getNum()) {
                        bean.setNum(BigDecimal.valueOf(0L));
                    }
                    if (null == bean.getLeaseDays()) {
                        bean.setLeaseDay(0L);
                    }
                    BigDecimal leasePrice = bean.getLeasePrice();
                    BigDecimal num = bean.getNum();
                    BigDecimal leaseDays = new BigDecimal(bean.getLeaseDays());
                    BigDecimal costs = leasePrice.multiply(num).multiply(leaseDays);
                    if(costs!=null){
                        totalCostLease = totalCostLease.add(costs);
                    }
                    bean.setCosts(costs);
                }
                List<SltLeaseInfo> lease = Convert.toList(SltLeaseInfo.class, leaseList);

                //丢失费用明细
                BigDecimal totalCostLose = BigDecimal.valueOf(0.00);
                List<SltAgreementInfo> loseList = new ArrayList<>();

                for (SltAgreementInfo info : sltAgreementInfo) {
                    List<SltAgreementInfo> oneOfList = sltAgreementInfoMapper.getLoseList(info);
                    loseList.addAll(oneOfList);
                }

                for (SltAgreementInfo bean : loseList) {
                    if (null == bean.getBuyPrice()) {
                        bean.setBuyPrice(BigDecimal.valueOf(0.00));
                    }
                    if (null == bean.getNum()) {
                        bean.setNum(BigDecimal.valueOf(0L));
                    }
                    BigDecimal buyPrice = bean.getBuyPrice();
                    BigDecimal num = bean.getNum();
                    // 原价 x 数量
                    BigDecimal costs = buyPrice.multiply(num);
                    if(costs!=null){
                        totalCostLose = totalCostLose.add(costs);
                    }
                    //计算租赁费用
                    bean.setCosts(costs);
                }
                List<SltLeaseInfo> lose = Convert.toList(SltLeaseInfo.class, loseList);

                //维修费用明细
                BigDecimal totalCostRepair = BigDecimal.valueOf(0.00);
                List<SltAgreementInfo> repairList = new ArrayList<>();

                for (SltAgreementInfo info : sltAgreementInfo) {
                    List<TmTask> taskList = taskMapper.getTaskIdList(info);
                    if (null != taskList && !taskList.isEmpty()) {
                        List<SltAgreementInfo> repairDetailsList = sltAgreementInfoMapper.getRepairDetailsList(info, taskList);
                        repairList.addAll(repairDetailsList);
                    }
                }
                for (SltAgreementInfo bean : repairList) {
                    if (bean.getCosts()!=null && (bean.getPartType().equals("收费"))) {
                        totalCostRepair = totalCostRepair.add(bean.getCosts());
                    }
                }
                List<SltLeaseInfo> repair = Convert.toList(SltLeaseInfo.class, repairList);

                //报废费用明细
                BigDecimal totalCostScrap = BigDecimal.valueOf(0.00);
                List<SltAgreementInfo> scrapList = new ArrayList<>();
                for (SltAgreementInfo info : sltAgreementInfo) {
                    List<TmTask> taskList = taskMapper.getTaskIdList(info);
                    if (null != taskList && !taskList.isEmpty()) {
                        List<SltAgreementInfo> scrapDetailsList = sltAgreementInfoMapper.getScrapDetailsList(info, taskList);
                        scrapList.addAll(scrapDetailsList);
                    }
                }

                for (SltAgreementInfo bean : scrapList) {
                    if (bean.getCosts()!=null && (bean.getPartType().equals("收费"))) {
                        totalCostScrap = totalCostScrap.add(bean.getCosts());
                    }
                }
                List<SltLeaseInfo> scrap = Convert.toList(SltLeaseInfo.class, scrapList);

                //减免费用明细
                BigDecimal totalCostReduction = BigDecimal.valueOf(0.00);
                List<SltAgreementReduce> reductionList = new ArrayList<>();
//            if (sltAgreementInfo.getAgreementId()!=null){
//                SltAgreementReduce bean =new SltAgreementReduce();
//                bean.setAgreementId(sltAgreementInfo.getAgreementId());
//                reductionList = sltAgreementRecudceMapper.getReductionList(bean);
//                for (SltAgreementReduce reduction : reductionList){
//                    if(reduction.getLeaseMoney()!=null){
//                        totalCostReduction = totalCostReduction.add(reduction.getLeaseMoney());
//                    }
//                }
//            }

                for (SltAgreementInfo info : sltAgreementInfo) {
                    if (info.getAgreementId() != null){
                        SltAgreementReduce bean =new SltAgreementReduce();
                        bean.setAgreementId(info.getAgreementId());
                        List<SltAgreementReduce> oneOfList = sltAgreementRecudceMapper.getReductionList(bean);
                        reductionList.addAll(oneOfList);
                    }

                }
                for (SltAgreementReduce reduction : reductionList) {
                    if(reduction.getLeaseMoney()!=null){
                        totalCostReduction = totalCostReduction.add(reduction.getLeaseMoney());
                    }
                }
                List<SltLeaseInfo> reduction = Convert.toList(SltLeaseInfo.class, reductionList);
                String projectName = handleData(projectNames);
                String unitName = handleData(unitNames);
                expOutExcelAll(response,lease,lose,repair,scrap,reduction,fileName,projectName,unitName,totalCostLease,totalCostLose,totalCostRepair,totalCostScrap,totalCostReduction);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
    }


    /**
     * 结算记录查询--导出全部明细
     */
    @ApiOperation(value = "导出全部结算费用明细")
    @PreventRepeatSubmit
    @SysLog(title = "结算记录查询", businessType = OperaType.EXPORT, logType = 1,module = "结算记录查询->导出全部结算费用明细")
    @PostMapping("/exportAlls")
    public void exportAlls(HttpServletResponse response, SltAgreementInfo sltAgreementInfo) {
        try {
            String fileName = "结算费用明细";
            String projectName = sltAgreementInfo.getProjectName();
            String unitName = sltAgreementInfo.getUnitName();

            //租赁费用明细
            BigDecimal totalCostLease = BigDecimal.valueOf(0.00);
            List<SltAgreementInfo> leaseList = new ArrayList<>();
            List<SltAgreementInfo> oneOfListLease = sltAgreementInfoMapper.getLeaseList(sltAgreementInfo);
            leaseList.addAll(oneOfListLease);
            for (SltAgreementInfo bean : leaseList) {
                if (null == bean.getLeasePrice()) {
                    bean.setLeasePrice(BigDecimal.valueOf(0.00));
                }
                if (null == bean.getNum()) {
                    bean.setNum(BigDecimal.valueOf(0L));
                }
                if (null == bean.getLeaseDays()) {
                    bean.setLeaseDay(0L);
                }
                BigDecimal leasePrice = bean.getLeasePrice();
                BigDecimal num = bean.getNum();
                BigDecimal leaseDays = new BigDecimal(bean.getLeaseDays());
                BigDecimal costs = leasePrice.multiply(num).multiply(leaseDays);
                if(costs!=null){
                    totalCostLease = totalCostLease.add(costs);
                }
                bean.setCosts(costs);
            }
            List<SltLeaseInfo> lease = Convert.toList(SltLeaseInfo.class, leaseList);

            //丢失费用明细
            BigDecimal totalCostLose = BigDecimal.valueOf(0.00);
            List<SltAgreementInfo> loseList = new ArrayList<>();

            List<SltAgreementInfo> oneOfListLose = sltAgreementInfoMapper.getLoseList(sltAgreementInfo);
            loseList.addAll(oneOfListLose);
            for (SltAgreementInfo bean : loseList) {
                if (null == bean.getBuyPrice()) {
                    bean.setBuyPrice(BigDecimal.valueOf(0.00));
                }
                if (null == bean.getNum()) {
                    bean.setNum(BigDecimal.valueOf(0L));
                }
                BigDecimal buyPrice = bean.getBuyPrice();
                BigDecimal num = bean.getNum();
                // 原价 x 数量
                BigDecimal costs = buyPrice.multiply(num);
                if(costs!=null){
                    totalCostLose = totalCostLose.add(costs);
                }
                //计算租赁费用
                bean.setCosts(costs);
            }
            List<SltLeaseInfo> lose = Convert.toList(SltLeaseInfo.class, loseList);

            //维修费用明细
            BigDecimal totalCostRepair = BigDecimal.valueOf(0.00);
            List<SltAgreementInfo> repairList = new ArrayList<>();
            List<TmTask> taskListRepair = taskMapper.getTaskIdList(sltAgreementInfo);
            if (null != taskListRepair && !taskListRepair.isEmpty()) {
                List<SltAgreementInfo> repairDetailsList = sltAgreementInfoMapper.getRepairDetailsList(sltAgreementInfo, taskListRepair);
                repairList.addAll(repairDetailsList);
            }
            for (SltAgreementInfo bean : repairList) {
                if (bean.getCosts()!=null && (bean.getPartType().equals("收费"))) {
                    totalCostRepair = totalCostRepair.add(bean.getCosts());
                }
            }
            List<SltLeaseInfo> repair = Convert.toList(SltLeaseInfo.class, repairList);

            //报废费用明细
            BigDecimal totalCostScrap = BigDecimal.valueOf(0.00);
            List<SltAgreementInfo> scrapList = new ArrayList<>();
            List<TmTask> taskListScrap = taskMapper.getTaskIdList(sltAgreementInfo);
            if (null != taskListScrap && !taskListScrap.isEmpty()) {
                List<SltAgreementInfo> scrapDetailsList = sltAgreementInfoMapper.getScrapDetailsList(sltAgreementInfo, taskListScrap);
                scrapList.addAll(scrapDetailsList);
            }
            for (SltAgreementInfo bean : scrapList) {
                if (bean.getCosts()!=null && (bean.getPartType().equals("收费"))) {
                    totalCostScrap = totalCostScrap.add(bean.getCosts());
                }
            }
            List<SltLeaseInfo> scrap = Convert.toList(SltLeaseInfo.class, scrapList);

            //减免费用明细
            BigDecimal totalCostReduction = BigDecimal.valueOf(0.00);
            List<SltAgreementReduce> reductionList = new ArrayList<>();
            if (sltAgreementInfo.getAgreementId()!=null){
                SltAgreementReduce bean =new SltAgreementReduce();
                bean.setAgreementId(sltAgreementInfo.getAgreementId());
                reductionList = sltAgreementRecudceMapper.getReductionList(bean);
                for (SltAgreementReduce reduction : reductionList){
                    if(reduction.getLeaseMoney()!=null){
                        totalCostReduction = totalCostReduction.add(reduction.getLeaseMoney());
                    }
                }
            }
            List<SltLeaseInfo> reduction = Convert.toList(SltLeaseInfo.class, reductionList);

            expOutExcelAlls(response,lease,lose,repair,scrap,reduction,fileName,projectName,unitName,totalCostLease,totalCostLose,totalCostRepair,totalCostScrap,totalCostReduction);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
    }

    /**
     * 修改结算信息
     */
    @ApiOperation(value = "修改结算信息")
    @PreventRepeatSubmit
    @RequiresPermissions("settlement:info:edit")
    @SysLog(title = "结算信息", businessType = OperaType.UPDATE, logType = 1,module = "仓储管理->修改结算信息")
    @PutMapping
    public AjaxResult edit(@RequestBody SltAgreementInfo sltAgreementInfo) {
        try {
            return toAjax(sltAgreementInfoService.updateSltAgreementInfo(sltAgreementInfo));
        } catch (Exception e) {
            return error("系统错误, " + e.getMessage());
        }
    }

    /**
     * 删除结算信息
     */
    @ApiOperation(value = "删除结算信息")
    @PreventRepeatSubmit
    @RequiresPermissions("settlement:info:remove")
    @SysLog(title = "结算信息", businessType = OperaType.DELETE, logType = 1,module = "仓储管理->删除结算信息")
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(sltAgreementInfoService.deleteSltAgreementInfoByIds(ids));
    }

    /**
     * 提交结算清单
     */
    @ApiOperation(value = "提交结算清单")
    @PostMapping("/submitCosts")
    public AjaxResult submitCosts(@RequestBody SltInfoVo sltInfoVo) {
        return toAjax(sltAgreementInfoService.submitCosts(sltInfoVo));
    }

    /**
     * 结算审批列表
     */
    @ApiOperation(value = "结算审批列表")
    @GetMapping("/getSltList")
    public TableDataInfo getSltList(SltAgreementInfo bean) {
        startPage();
        List<SltAgreementInfo> list = sltAgreementInfoService.getSltList(bean);
        return getDataTable(list);
    }

    /**
     * 丢失报表--列表
     */
    @ApiOperation(value = "丢失报表list查询")
    @GetMapping("/getLostReportList")
    public TableDataInfo getLostReportList(SltAgreementInfo bean) {
        startPage();
        List<SltAgreementInfo> list = sltAgreementInfoService.getLostReportList(bean);
        return getDataTable(list);
    }

    /**
     * 维修报表--列表
     */
    @ApiOperation(value = "维修报表list查询")
    @GetMapping("/getRepairReportList")
    public TableDataInfo getRepairReportList(SltAgreementInfo bean) {
        startPage();
        List<SltAgreementInfo> list = sltAgreementInfoService.getRepairReportList(bean);
        return getDataTable(list);
    }

    /**
     * 报废报表--列表
     */
    @ApiOperation(value = "报废报表list查询")
    @GetMapping("/getScrapReportList")
    public TableDataInfo getScrapReportList(SltAgreementInfo bean) {
        startPage();
        List<SltAgreementInfo> list = sltAgreementInfoService.getScrapReportList(bean);
        return getDataTable(list);
    }

    /**
     * 已结算报表--列表
     */
    @ApiOperation(value = "已结算报表list查询")
    @GetMapping("/getSltReportedList")
    public TableDataInfo getSltReportedList(SltAgreementInfo bean) {
        startPage();
        List<SltAgreementInfo> list = sltAgreementInfoService.getSltReportedList(bean);
        return getDataTable(list);
    }

    /**
     * 未结算报表--列表
     */
    @ApiOperation(value = "未结算报表list查询")
    @GetMapping("/getSltReportList")
    public TableDataInfo getSltReportList(SltAgreementInfo query) {
        long startTime = System.currentTimeMillis();
        try {
            // 参数预处理和校验
            if (query == null) {
                query = new SltAgreementInfo();
            }
            startPage();

            // ----------- 查询未结算的全部协议 ---------------
            List<SltAgreementInfo> list = sltAgreementInfoService.getSltReportList(query);

            // 如果没有数据，直接返回空结果
            if (CollectionUtils.isEmpty(list)) {
                return getDataTable(new ArrayList<>());
            }

            log.info("查询到未结算协议数量: {}", list.size());

            // ----------- 给查询出来的协议设置权限控制（例如只查询工器具） ---------------
            int settlementType = sltAgreementInfoService.checkLoginUserHasSettlementPermission();

            // ---------  拿到list中所有的agreementId存成集合，给每个info赋值 ------------------
            List<Long> agreementIdsArray = list.stream()
                .map(SltAgreementInfo::getAgreementId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

            if (agreementIdsArray.isEmpty()) {
                return getDataTable(new ArrayList<>());
            }

            // ---------  定义返回集合 ------------------
            List<SltInfoVo> dataList = new ArrayList<>(list.size());

            // 批量处理，减少单个查询
            list.forEach(info -> {
                try {
                    info.setSettlementType(settlementType);
                    info.setAgreementIds(agreementIdsArray);

                    // 查询每个协议的各项费用明细
                    SltInfoVo vo = sltAgreementInfoService.getSltInfoReportBatch(info);
                    if (vo != null && !ObjectUtil.isEmpty(vo)) {
                        vo.setAgreementId(info.getAgreementId());
                        vo.setAgreementCode(info.getAgreementCode());
                        dataList.add(vo);
                    }
                } catch (Exception e) {
                    log.error("处理协议 {} 时出错: {}", info.getAgreementCode(), e.getMessage());
                }
            });

            // 移除领、修、丢、废4项都没有明细的结算信息
//            dataList.removeIf(vo -> CollectionUtils.isEmpty(vo.getLeaseList())
//                    && CollectionUtils.isEmpty(vo.getRepairList())
//                    && CollectionUtils.isEmpty(vo.getScrapList())
//                    && CollectionUtils.isEmpty(vo.getLoseList())
//            );

            long endTime = System.currentTimeMillis();
            log.info("未结算报表查询完成，耗时: {}ms，返回数据: {}条", (endTime - startTime), dataList.size());

            TableDataInfo resultTableData = getDataTable(dataList);
            if (RequestContext.get("unSltAgreementListCount") != null) {
                if (RequestContext.get("unSltAgreementListCount") instanceof Long) {
                    resultTableData.setTotal(((long) RequestContext.get("unSltAgreementListCount")));
                }
                if (RequestContext.get("unSltAgreementListCount") instanceof Integer) {
                    resultTableData.setTotal(((Integer) RequestContext.get("unSltAgreementListCount")));
                }
            }

            return resultTableData;
        } catch (Exception e) {
            log.error("查询未结算报表失败", e);
            return getDataTable(new ArrayList<>());
        } finally {
            RequestContext.clear();
            sltAgreementInfoService.clearCache();
        }
    }

    /**
     * 进行结算审批
     */
    @ApiOperation(value = "进行结算审批")
    @PostMapping("/costExamine")
    public AjaxResult costExamine(@RequestBody SltAgreementApply apply) {
        try {
            return sltAgreementInfoService.costExamine(apply);
        } catch (Exception e) {
            return error("系统错误, " + e.getMessage());
        }
    }

    /**
     * 查询租赁区间费用明细
     */
    @ApiOperation(value = "查询租赁区间费用明细")
    //@RequiresPermissions("settlement:info:periodCost")
    @GetMapping("/leasePeriodCostDetails")
    public TableDataInfo leasePeriodCostDetails(PeriodCostQueryDto queryDto) {
        try {
            //startPage();
            List<PeriodCostResultVo> list = sltAgreementInfoService.selectPeriodCostList(queryDto);
            return getDataTable(list);
        } catch (Exception e) {
            log.error("查询区间费用失败", e);
            return getDataTable(new ArrayList<>());
        }
    }

    /**
     * 导出区间费用计算结果
     */
    @ApiOperation(value = "导出区间费用计算结果")
    //@RequiresPermissions("settlement:info:periodCostExport")
    @SysLog(title = "区间费用计算", module = "费用报表", operatorType = OperatorType.MANAGE)
    @PostMapping("/periodCost/export")
    public void exportPeriodCost(HttpServletResponse response, @RequestBody PeriodCostQueryDto queryDto) {
        try {
            List<PeriodCostResultVo> list = sltAgreementInfoService.selectPeriodCostList(queryDto);
            ExcelUtil<PeriodCostResultVo> util = new ExcelUtil<>(PeriodCostResultVo.class);
            util.exportExcel(response, list, "区间费用计算结果");
        } catch (Exception e) {
            log.error("导出区间费用失败", e);
        }
    }

    /**
     * 查询区间租赁费用汇总报表（按协议汇总）
     */
    @ApiOperation(value = "查询区间租赁费用汇总报表")
    //@RequiresPermissions("settlement:info:periodCostSummary")
    @GetMapping("leasePeriodCostList")
    public TableDataInfo leasePeriodCostList(PeriodCostQueryDto queryDto) {
        try {
            //startPage();
            List<PeriodCostSummaryVo> list = sltAgreementInfoService.selectPeriodCostSummary(queryDto);
            return getDataTable(list);
        } catch (Exception e) {
            log.error("查询区间费用汇总失败", e);
            return getDataTable(new ArrayList<>());
        }
    }

    /**
     * 导出区间费用汇总结果
     */
    @ApiOperation(value = "导出区间费用汇总结果")
    @RequiresPermissions("settlement:info:periodCostSummaryExport")
    @SysLog(title = "区间费用汇总", module = "费用报表", operatorType = OperatorType.MANAGE)
    @PostMapping("/periodCost/summary/export")
    public void exportPeriodCostSummary(HttpServletResponse response, @RequestBody PeriodCostQueryDto queryDto) {
        try {
            List<PeriodCostSummaryVo> list = sltAgreementInfoService.selectPeriodCostSummary(queryDto);
            ExcelUtil<PeriodCostSummaryVo> util = new ExcelUtil<>(PeriodCostSummaryVo.class);
            util.exportExcel(response, list, "区间费用汇总结果");
        } catch (Exception e) {
            log.error("导出区间费用汇总失败", e);
        }
    }
}
