package com.xhpc.user.service.impl;

import cn.hutool.extra.mail.MailUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.xhpc.common.core.utils.DateUtils;
import com.xhpc.common.core.utils.bean.BeanUtils;
import com.xhpc.common.domain.XhpcChargingStation;
import com.xhpc.common.redis.service.RedisService;
import com.xhpc.common.security.service.TokenService;
import com.xhpc.common.util.DateUtil;
import com.xhpc.common.util.UserTypeUtil;
import com.xhpc.user.constant.InvoiceMapHistoryOrderStatusConst;
import com.xhpc.user.constant.InvoiceStatusConst;
import com.xhpc.user.constant.IsReadStatusConst;
import com.xhpc.user.domain.*;
import com.xhpc.user.domain.InvoicedOrderResponse.ItemsDTO;
import com.xhpc.user.domain.InvoicedOrderResponse.ItemsDTO.OrderDatasDTO;
import com.xhpc.user.mapper.*;
import com.xhpc.user.pojo.XhpcInvoice;
import com.xhpc.user.pojo.XhpcInvoiceMapHistoryOrder;
import com.xhpc.user.service.XhpcInvoiceService;
import com.xhpc.order.domain.XhpcHistoryOrder;
import com.xhpc.system.api.domain.SysUser;
import com.xhpc.system.api.model.LoginUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * XhpcInvoiceService的实现类
 *
 * @author WH
 * @date 2021/12/20 14:09
 * @since version-1.0
 */
@Service
public class XhpcInvoiceServiceImpl implements XhpcInvoiceService {

    @Resource
    XhpcInvoiceMapper xhpcInvoiceMapper;
    @Resource
    XhpcInvoiceMapHistoryOrderMapper xhpcInvoiceMapHistoryOrderMapper;
    @Resource
    XhpcOperatorMapper xhpcOperatorMapper;
    @Resource
    XhpcChargingStationMapper xhpcChargingStationMapper;
    @Resource
    SysUserMapper sysUserMapper;
    @Resource
    XhpcHistoryOrderMapper xhpcHistoryOrderMapper;
    @Resource
    Environment environment;
    @Resource
    RedisService redisService;
    @Resource
    TokenService tokenService;

    /**
     * 通过requestData中的申请人、申请人类型、发票类型、发票状态、发票起始时间、发票申请终止时间、开票起始时间、开票终点时间、当前所在页数、当前页所要显示几行，来查询发票列表信息
     *
     * @param requestData 传递过来的查询参数
     * @return AllInvoiceOrdersResponse 发票列表对象
     * @author WH
     * @date 2021/12/21 16:02
     * @since version-1.0
     */
    @Override
    public AllInvoiceOrdersResponse findAllInvoiceOrders(AllInvoiceOrdersRequest requestData) {
        //计算分页索引
        requestData.setCurrentPage((requestData.getCurrentPage() - 1) * requestData.getItems());
        //获取每张发票信息
        LoginUser loginUser = tokenService.getLoginUser();
        requestData.setTenantId(loginUser.getTenantId());
        List<XhpcInvoice> xhpcInvoiceList = xhpcInvoiceMapper.selectAllInvoiceOrdersByCondition(requestData);
        //对拷，放置到itemsDTO中,然后将itemsDTO存放到itemsDTOList中
        ArrayList<AllInvoiceOrdersResponse.ItemsDTO> itemsDTOList = new ArrayList<>();
        for (XhpcInvoice xhpcInvoice : xhpcInvoiceList) {
            AllInvoiceOrdersResponse.ItemsDTO itemsDTO = new AllInvoiceOrdersResponse.ItemsDTO();
            itemsDTO.setInvoiceId(xhpcInvoice.getInvoiceId());
            itemsDTO.setInvoiceType(xhpcInvoice.getInvoiceType());
            itemsDTO.setInvoiceStatus(xhpcInvoice.getInvoiceStatus());
            itemsDTO.setCreator(xhpcInvoice.getCreator());
            itemsDTO.setCreatorType(xhpcInvoice.getCreatorType());
            itemsDTO.setInvoiceMoney(xhpcInvoice.getInvoiceMoney());
            itemsDTO.setStatus(xhpcInvoice.getStatus());
            itemsDTO.setOrderOperatorName(xhpcInvoice.getOrderOperatorName());
            itemsDTO.setInvoiceOperatorName(xhpcInvoice.getInvoiceOperatorName());
            itemsDTO.setCreateTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, xhpcInvoice.getCreateTime()));
            if (xhpcInvoice.getInvoicingTime() != null) {
                itemsDTO.setInvoicingTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, xhpcInvoice.getInvoicingTime()));
            }
            itemsDTO.setDrawer(xhpcInvoice.getDrawer());

            itemsDTOList.add(itemsDTO);
        }
        AllInvoiceOrdersResponse allInvoiceOrdersResponse = new AllInvoiceOrdersResponse();
        allInvoiceOrdersResponse.setItems(itemsDTOList);
        //获取根据条件查询出来的发票总条数
        Long sumItemsInvoice = xhpcInvoiceMapper.sumItemsInvoice(requestData);
        allInvoiceOrdersResponse.setTotalItems(sumItemsInvoice);
        //查询所有已开发票总金额
        BigDecimal allInvoicedMoney = xhpcInvoiceMapper.allInvoicedMoney();
        if (allInvoicedMoney == null) {
            //如果没有开任何发票，那么总金额就设置成0.00
            allInvoicedMoney = new BigDecimal("0.00");
        }
        allInvoiceOrdersResponse.setInvoicedSumMoney(allInvoicedMoney);
        //查询所有未开发票总金额
        BigDecimal allNotInvoicedMoney = xhpcInvoiceMapper.allNotInvoicedMoney();
        if (allNotInvoicedMoney == null) {
            //如果没有任何未开发票，那么总金额就设置成0.00
            allNotInvoicedMoney = new BigDecimal("0.00");
        }
        allInvoiceOrdersResponse.setNotInvoiceSumMoney(allNotInvoicedMoney);
        return allInvoiceOrdersResponse;
    }

    /**
     * 存储成功开发票的状态，将开票信息入库，并向指定用户的邮箱发送短信
     *
     * @param requestData 要入库的信息
     * @return Boolean 成功还是失败
     * @author WH
     * @date 2021/12/22 14:59
     * @since version-1.0
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean invoiceToUser(InvoiceToUserRequest requestData) {

        if (requestData.getInvoicingTime() == null || "".equals(requestData.getInvoicingTime())) {
            //获取当前时间
            requestData.setInvoicingTime(DateUtil.getYyyyMmDdHhMmSs());
        }
        //根据操作人的id，查询操作人的名字
        SysUser sysUser = sysUserMapper.selectUserById(Long.valueOf(requestData.getDrawer()));
        requestData.setDrawer(sysUser.getNickName());
        //发送电子发票pdf到接收者邮箱
        XhpcInvoice xhpcInvoice = xhpcInvoiceMapper.selectByPrimaryKey(requestData.getInvoiceId());
        String receiveEmail = xhpcInvoice.getReceiveEmail();
        //从阿里云上下载下来电子发票
        String fileUrl = requestData.getEletricInvoiceUrl();
        File electricInvoiceFile = new File(environment.getProperty("file.serverStoreDisposableFileLocation") + "ElectricInvoice.pdf");
        try {
            //参数1 文件下载路径
            //参数2 文件存放位置
            //服务器响应404 表示服务器找不到客户端所请求的资源
            HttpUtil.downloadFile(fileUrl, electricInvoiceFile);
        } catch (Exception e) {
            throw new RuntimeException("在阿里云上无法找到该文件，请检查上传的图片路径是否完整或有误");
        }
        try {
            MailUtil.send(receiveEmail, "【翔桦充电】电子发票", "邮件来自翔桦充电", false, electricInvoiceFile);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return Boolean.FALSE;
        } finally {
            if (electricInvoiceFile.exists()) {
                electricInvoiceFile.delete();
            }
        }
        System.out.println("<<<<<<<<<<5555<<<<<<<<<发票路径>>>>>>>>>>444>>>>>>>>"+fileUrl);
        //更新发票数据,并设置用户未阅读状态
        Long successFlag = xhpcInvoiceMapper.updateInvoiceToUser(requestData);
        if (successFlag == 0) {
            throw new RuntimeException("无法更新指定发票，传入的数据有问题");
        }
        //将该用户未阅读的数量放入到redis中
        putNoReadInvoiceCountIntoRedis(requestData);
        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void failInvoiceToUser(InvoiceToUserRequest requestData) {

        if (requestData.getInvoicingTime() == null || "".equals(requestData.getInvoicingTime())) {
            //获取当前时间
            requestData.setInvoicingTime(DateUtil.getYyyyMmDdHhMmSs());
        }
        //根据操作人的id，查询操作人的名字
        SysUser sysUser = sysUserMapper.selectUserById(Long.valueOf(requestData.getDrawer()));
        requestData.setDrawer(sysUser.getNickName());
        //更新发票状态
        xhpcInvoiceMapper.updateFailInvoiceToUser(requestData);
        //解除锁定
        xhpcInvoiceMapHistoryOrderMapper.updateUnlockHistoryOrdersByInvoiceId(requestData.getInvoiceId());
        //将该用户未阅读的数量放入到redis中
        putNoReadInvoiceCountIntoRedis(requestData);
    }

    /**
     * 将该用户没有阅读的发票的数量放入到Redis中保存，供别人调用
     *
     * @author WH
     * @date 2021/12/30 13:54
     * @since version-1.0
     */
    private void putNoReadInvoiceCountIntoRedis(InvoiceToUserRequest requestData) {

        XhpcInvoice xhpcInvoice = xhpcInvoiceMapper.selectByPrimaryKey(requestData.getInvoiceId());
        String redisKey = generateRedisKey(xhpcInvoice);
        redisService.setCacheObject(redisKey, 1L);
//        if (redisService.getCacheObject(redisKey) == null) {
//            redisService.setCacheObject(redisKey, 1L);
//        } else {
//            Long noReadCount = redisService.getCacheObject(redisKey);
//            noReadCount = noReadCount + 1;
//            redisService.setCacheObject(redisKey, noReadCount);
//        }
    }

    @Override
    public InvoiceTitleResponse findTitleInfo(String firmName) {

        List<XhpcInvoice> xhpcInvoiceList = xhpcInvoiceMapper.selectInvoiceTitleInfo(firmName);
        InvoiceTitleResponse invoiceTitleResponse = new InvoiceTitleResponse();
        //如果没有记录，则返回空包装类
        if (xhpcInvoiceList.size() == 0) {
            ArrayList<InvoiceTitleResponse.DataDTO> dataDTOList = new ArrayList<>();
            invoiceTitleResponse.setData(dataDTOList);
            return invoiceTitleResponse;
        }
        ArrayList<InvoiceTitleResponse.DataDTO> dataDTOList = new ArrayList<>();
        for (XhpcInvoice xhpcInvoice : xhpcInvoiceList) {
            InvoiceTitleResponse.DataDTO dataDTO = new InvoiceTitleResponse.DataDTO();
            dataDTO.setFirmName(xhpcInvoice.getTitleContent());
            dataDTO.setDutyNumber(xhpcInvoice.getDutyNumber());
            dataDTOList.add(dataDTO);
        }
        invoiceTitleResponse.setData(dataDTOList);
        return invoiceTitleResponse;
    }

    /**
     * 查询用户输入的最后一次的开发票所填写的信息
     *
     * @param creatorId   用户id
     * @param creatorType 用户类型
     * @return 要回显的数据
     * @author WH
     * @date 2021/12/23 17:23
     * @since version-1.0
     */
    @Override
    public TitleResponse findUserLastInputInfo(Long creatorId, Integer creatorType) {

        XhpcInvoice xhpcInvoice = xhpcInvoiceMapper.selectUserLastInputInvoiceInfo(creatorId, creatorType);
        TitleResponse titleResponse = new TitleResponse();
        //如果数据库本身就没有数据，那么就返回空实体类对象
        if (xhpcInvoice == null) {
            return titleResponse;
        }
        BeanUtils.copyProperties(xhpcInvoice, titleResponse);
        return titleResponse;

    }

    /**
     * 根据用户id，用户类型，要查询的当前时间的年月日，查询该用户3个月内可以开发票的历史订单
     *
     * @param invoicedOrdersRequest 查询条件
     * @return 要返回的数据的封装类
     * @author WH
     * @date 2021/12/24 10:42
     * @since version-1.0
     */
    @Override
    public InvoicedOrderResponse findUserHistoryOrders(InvoicedOrdersRequest invoicedOrdersRequest) {
        System.out.println("<<<<<<<<<<111<<<<<<<<<查询开票信息>>>>>>>>>>111>>>>>>>>"+invoicedOrdersRequest.toString());
        //自动生成当前时间
        if (invoicedOrdersRequest.getCurrentTime() == null || "".equals(invoicedOrdersRequest.getCurrentTime())) {
            Date currentDate = new Date();
            String strTime = DateUtils.parseDateToStr(currentDate);
            invoicedOrdersRequest.setCurrentTime(strTime);
        }
        //先查询该用户被锁定了的订单，过滤掉它
        List<Integer> lockOrderNumberList = xhpcInvoiceMapHistoryOrderMapper.findLockOrdersByUserIdAndUserType(invoicedOrdersRequest);
        System.out.println("<<<<<<<<<<111<<<<<<<<<询该用户被锁定了的订单>>>>>>>>>>111>>>>>>>>");
        //查询该用户3个月内可以开发票的历史订单
        List<Map<String, Object>> xhpcHistoryOrderList = xhpcHistoryOrderMapper.findByCondition(invoicedOrdersRequest, lockOrderNumberList);
        System.out.println("<<<<<<<<<<111<<<<<<<<<用户3个月内可以开发票>>>>>>>>>>111>>>>>>>>");
        InvoicedOrderResponse invoicedOrderResponse = new InvoicedOrderResponse();
        //没有则直接返回空对象出去
        if (xhpcHistoryOrderList.size() == 0) {
            return invoicedOrderResponse;
        }
        //设置该用户3个月内可以开发票的历史订单数量
        invoicedOrderResponse.setTotalItems(xhpcHistoryOrderList.size());
        //查询该用户所有可以开的发票的历史订单数量
        Long allOrders = xhpcHistoryOrderMapper.findAllOrdersByCondition(invoicedOrdersRequest, lockOrderNumberList);
        invoicedOrderResponse.setAllTotalItems(Math.toIntExact(allOrders));
        //监测器，监测集合中的时间是否发生改变，如果发生改变，则表示是其他月份的记录
        String monitor = xhpcHistoryOrderList.size() > 0 ? xhpcHistoryOrderList.get(0).get("belongsTime").toString() : "";
        //该集合用来存放一整个月的记录
        ArrayList<Map<String, Object>> split = new ArrayList<>();
        //该集合存放所有分好组的每个月的记录
        Map<String, Object> allGroupingRecords = new HashMap<>();
        for (Map<String, Object> order : xhpcHistoryOrderList) {
            if (!monitor.equals(order.get("belongsTime").toString())) {
                allGroupingRecords.put(monitor, split);
                split = new ArrayList<>();
                monitor = order.get("belongsTime").toString();
            }
            split.add(order);
        }
        allGroupingRecords.put(monitor, split);
        //存放至包装类中
        Set<String> keys = allGroupingRecords.keySet();
        //对key进行反向排序，保证封装的数据是反着的
        ArrayList<String> tempKeyList = new ArrayList<>();
        for (String key : keys) {
            tempKeyList.add(key);
        }
        //创建一个游标在迭代器末尾的迭代器
        ListIterator<String> stringListIterator = tempKeyList.listIterator(tempKeyList.size());
        //然后反向遍历
        ArrayList<String> keyList = new ArrayList<>();
        while (stringListIterator.hasPrevious()) {
            keyList.add(stringListIterator.previous());
        }
        ArrayList<ItemsDTO> itemsDTOS = new ArrayList<>();
        //定义一个计数器，只要前3个月的记录
        int count = 0;
        for (String key : keyList) {
            count++;
            if (count == 13) {
                break;
            }
            ItemsDTO itemsDTO = new ItemsDTO();
            itemsDTO.setOrderScopeTime(key);
            ArrayList<OrderDatasDTO> orderDatasDTOS = new ArrayList<>();
            ArrayList<Map<String, Object>> dataList = (ArrayList<Map<String, Object>>) allGroupingRecords.get(key);
            for (Map<String, Object> data : dataList) {
                OrderDatasDTO orderDatasDTO = new OrderDatasDTO();
                orderDatasDTO.setOrderId((Long) data.get("historyOrderId"));
                orderDatasDTO.setOrderNumber((String) data.get("serialNumber"));
                orderDatasDTO.setOrderMoney(new BigDecimal(data.get("actPrice").toString()));

//                if(data.get("placeholderMoney") !=null && new BigDecimal(data.get("placeholderMoney").toString()).compareTo(new BigDecimal(0))>0){
//                    orderDatasDTO.setTotalMoney(new BigDecimal(data.get("actPrice").toString()).add(new BigDecimal(data.get("placeholderMoney").toString())));
//                }else{
//                    orderDatasDTO.setTotalMoney(new BigDecimal(data.get("actPrice").toString()));
//                }
//                if(data.get("placeholderMoney")!=null){
//                    orderDatasDTO.setPlaceholderMoney(new BigDecimal(data.get("placeholderMoney").toString()));
//                }
                //因为数据库中存储的时间类型为datetime，所以Mybatis会将其转换为LocalDateTime类型对象，我们不能直接得到Date，所以我们需要对其进行转换。
                LocalDateTime createTime = (LocalDateTime) data.get("createTime");
                ZoneId zoneId = ZoneId.systemDefault();
                ZonedDateTime zdt = createTime.atZone(zoneId);
                Date date = Date.from(zdt.toInstant());
                orderDatasDTO.setOrderTime(DateUtils.parseDateToStr(date));
                orderDatasDTOS.add(orderDatasDTO);
            }
            itemsDTO.setOrderDatas(orderDatasDTOS);
            itemsDTOS.add(itemsDTO);
            //因为List中的Map是有序的，所以，最后一个Map的key一定是最小月份时间，那么最小月份时间-1秒，则为前端下次需要传递进来的月份参数，这样我可以去查传递进来的月份参数的之前3个月的有记录的月份的记录。
            //注意：传入一个残缺的时间，如2021-10，将其解析成Date，那么会将其解析成表示2021-10-01 00:00:00这个时间的Date，该时间-1秒，就是上个月的最后时间
            Date date = DateUtils.parseDate(key);
            Calendar calendarTwo = DateUtil.getCalendar(date);
            calendarTwo.add(Calendar.SECOND, -1);
            Date nextQueryParamDate = calendarTwo.getTime();
            String nextQueryParamDateStr = DateUtils.parseDateToStr(nextQueryParamDate);
            invoicedOrderResponse.setRecordsMonth(nextQueryParamDateStr);
        }
        invoicedOrderResponse.setItems(itemsDTOS);
        try {
            LoginUser loginUser = tokenService.getLoginUser();
            getCreatorRead(loginUser.getUserid(),loginUser.getUserType(),loginUser.getTenantId());
        }catch (Exception e){
                e.printStackTrace();
        }
        return invoicedOrderResponse;

    }

    /**
     * 根据发票id，查询回显发票所需要的数据
     *
     * @param invoiceId 发票id
     * @return 数据封装对象
     * @author WH
     * @date 2021/12/27 13:12
     * @since version-1.0
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SpecificInvoicedResponse findSpecificInvoicedInfo(Long invoiceId) {

        //对拷发票部分数据
        XhpcInvoice xhpcInvoice = xhpcInvoiceMapper.selectByPrimaryKey(invoiceId);
        SpecificInvoicedResponse specificInvoicedResponse = new SpecificInvoicedResponse();
        //查不出来返回空包装类
        if (xhpcInvoice == null) {
            return specificInvoicedResponse;
        }
        specificInvoicedResponse.setCreatorTime(DateUtils.parseDateToStr(xhpcInvoice.getCreateTime()));
        specificInvoicedResponse.setReceiveEmail(xhpcInvoice.getReceiveEmail());
        specificInvoicedResponse.setTitleType(xhpcInvoice.getTitleType());
        specificInvoicedResponse.setTitleContent(xhpcInvoice.getTitleContent());
        specificInvoicedResponse.setDutyNumber(xhpcInvoice.getDutyNumber());
        specificInvoicedResponse.setInvoiceContent(xhpcInvoice.getInvoiceContent());
        specificInvoicedResponse.setInvoiceMoney(xhpcInvoice.getInvoiceMoney());
        specificInvoicedResponse.setStatus(xhpcInvoice.getStatus());
        specificInvoicedResponse.setFinanceNotes(xhpcInvoice.getFinanceNotes());
        //查询关联订单
        List<XhpcInvoiceMapHistoryOrder> historyOrdersList = xhpcInvoiceMapHistoryOrderMapper.findOrdersByInvoiceId(xhpcInvoice.getInvoiceId());
        //封装关联订单数据
        ArrayList<SpecificInvoicedResponse.HistoryOrdersDTO.HistoryOrdersDataDTO> historyOrdersDataDTOS = new ArrayList<>();
        for (XhpcInvoiceMapHistoryOrder xhpcInvoiceMapHistoryOrder : historyOrdersList) {
            SpecificInvoicedResponse.HistoryOrdersDTO.HistoryOrdersDataDTO historyOrdersDataDTO = new SpecificInvoicedResponse.HistoryOrdersDTO.HistoryOrdersDataDTO();
            historyOrdersDataDTO.setHistoryOrderId(xhpcInvoiceMapHistoryOrder.getHistoryOrderId());
            historyOrdersDataDTO.setActPrice(xhpcInvoiceMapHistoryOrder.getHistoryActPrice());
            historyOrdersDataDTO.setHistorySerialNumber(xhpcInvoiceMapHistoryOrder.getHistorySerialNumber());
            historyOrdersDataDTO.setOrderCreateTime(DateUtils.parseDateToStr(xhpcInvoiceMapHistoryOrder.getCreateTime()));
            historyOrdersDataDTOS.add(historyOrdersDataDTO);
        }
        SpecificInvoicedResponse.HistoryOrdersDTO historyOrdersDTO = new SpecificInvoicedResponse.HistoryOrdersDTO();
        historyOrdersDTO.setHistoryOrdersData(historyOrdersDataDTOS);
        historyOrdersDTO.setTotalItems(historyOrdersList.size());
        specificInvoicedResponse.setHistoryOrders(historyOrdersDTO);

        //如果用户在该发票还没有被处理时，点击查看该发票详情，那么就直接返回数据。
        if (xhpcInvoice.getStatus().equals(InvoiceStatusConst.INVOICING)) {
            return specificInvoicedResponse;
        }
        //如果用户已经查看了该发票，却再次调用该接口，那么就直接返回数据。
        if(xhpcInvoice.getIsRead()==null){
            return specificInvoicedResponse;
        }
        if (xhpcInvoice.getIsRead().equals(IsReadStatusConst.READED)) {
            return specificInvoicedResponse;
        }
        //一旦调了详情接口，就去掉该已开发票的未读状态，同时再次查询用户未读的数量，并将其设置到redis当中
        xhpcInvoiceMapper.updateByInvoiceId(invoiceId);
        Long notReadCount = xhpcInvoiceMapper.findNotReadCount(xhpcInvoice.getCreatorId(), xhpcInvoice.getCreatorType());
        String redisKey = generateRedisKey(xhpcInvoice);
        if (notReadCount == 0) {
            redisService.deleteObject(redisKey);
        } else {
            redisService.setCacheObject(redisKey, notReadCount);
        }
        try {
            LoginUser loginUser = tokenService.getLoginUser();
            getCreatorRead(loginUser.getUserid(),loginUser.getUserType(),loginUser.getTenantId());
        }catch (Exception e){

        }
        return specificInvoicedResponse;
    }

    /**
     * 将用户未读的发票数量-1
     *
     * @param xhpcInvoice 用户查看的发票
     * @author WH
     * @date 2021/12/30 13:55
     * @since version-1.0
     */
    private void reduceNoReadInvoiceCount(XhpcInvoice xhpcInvoice) {

        String redisKey = generateRedisKey(xhpcInvoice);
        if (redisService.getCacheObject(redisKey).equals(1)) {
            redisService.deleteObject(redisKey);
        } else {
            Integer noReadCount = redisService.getCacheObject(redisKey);
            noReadCount = noReadCount - 1;
            redisService.setCacheObject(redisKey, noReadCount);
        }
    }

    /**
     * 生成该用户在Redis中的唯一表示key
     *
     * @param xhpcInvoice 用户查看的发票
     * @author WH
     * @date 2021/12/30 13:52
     * @since version-1.0
     */
    private String generateRedisKey(XhpcInvoice xhpcInvoice) {

        String tenantId = xhpcInvoice.getTenantId();
        String redisKey = "global:invoice:" + tenantId + ":";
        switch (xhpcInvoice.getCreatorType()) {
            case 0:
                redisKey = redisKey + "C" + xhpcInvoice.getCreatorId();
                break;
            case 1:
                redisKey = redisKey + "L" + xhpcInvoice.getCreatorId();
                break;
            case 2:
                redisKey = redisKey + "ST" + xhpcInvoice.getCreatorId();
                break;
            case 3:
                redisKey = redisKey + "BE" + xhpcInvoice.getCreatorId();
                break;
            default:
                break;
        }
        return redisKey;
    }

    /**
     * 根据前端传递过来的请求参数，查询所需要的开发票历史记录
     *
     * @param invoiceHistoryRecordsRequest 请求参数
     * @return 所需要的开发票历史记录
     * @author WH
     * @date 2021/12/27 14:49
     * @since version-1.0
     */
    @Override
    public InvoiceHistoryRecordsResponse findInvoiceHistoryRecords(InvoiceHistoryRecordsRequest invoiceHistoryRecordsRequest) {
        //计算分页索引
        int startIndex = (int) ((invoiceHistoryRecordsRequest.getCurrentPage() - 1) * invoiceHistoryRecordsRequest.getItems());
        if (startIndex < 0) {
            startIndex = 0;
        }
        invoiceHistoryRecordsRequest.setCurrentPage(startIndex);
        //获取该用户所提交的每个发票信息
        List<XhpcInvoice> invoicesList = xhpcInvoiceMapper.findInvoicesByCreatorIdAndCreatorType(invoiceHistoryRecordsRequest);
        //如果为0，那么则返回空的实体类出去
        InvoiceHistoryRecordsResponse invoiceHistoryRecordsResponse = new InvoiceHistoryRecordsResponse();
        if (invoicesList.size() == 0) {
            return invoiceHistoryRecordsResponse;
        }
        //实体类对拷
        ArrayList<InvoiceHistoryRecordsResponse.ItemsDTO> itemsDTOS = new ArrayList<>();
        for (XhpcInvoice xhpcInvoice : invoicesList) {
            InvoiceHistoryRecordsResponse.ItemsDTO itemsDTO = new InvoiceHistoryRecordsResponse.ItemsDTO();
            itemsDTO.setInvoiceId(xhpcInvoice.getInvoiceId());
            itemsDTO.setCreateTime(DateUtils.parseDateToStr(xhpcInvoice.getCreateTime()));
            itemsDTO.setStatus(xhpcInvoice.getStatus());
            itemsDTO.setInvoicingMoney(xhpcInvoice.getInvoiceMoney());
            itemsDTO.setIsRead(xhpcInvoice.getIsRead());
            itemsDTOS.add(itemsDTO);
        }
        invoiceHistoryRecordsResponse.setItems(itemsDTOS);
        Long userInvoiceItems = xhpcInvoiceMapper.getUserInvoiceItemsByCreatorIdAndCreatorType(invoiceHistoryRecordsRequest.getCreatorId(), invoiceHistoryRecordsRequest.getCreatorType());
        invoiceHistoryRecordsResponse.setTotalItems(userInvoiceItems);

        try {
            LoginUser loginUser = tokenService.getLoginUser();
            getCreatorRead(loginUser.getUserid(),loginUser.getUserType(),loginUser.getTenantId());
        }catch (Exception e){

        }

        return invoiceHistoryRecordsResponse;
    }

    /**
     * 将用户申请的发票信息，保存到数据库中
     *
     * @param saveInvoiceInfoRequest 发票信息
     * @throws Exception 传入发票金额参数与内部该发票所包含的所有订单金额参数不一致出现，出现此异常
     * @author WH
     * @date 2021/12/28 14:33
     * @since version-1.0
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveInvoiceInfoYu(SaveInvoiceInfoRequest saveInvoiceInfoRequest) throws Exception {
        //判断传入的历史订单是否被其他发票包含
        List<Integer> historyOrderIds = saveInvoiceInfoRequest.getHistoryOrderIds();
        List<XhpcInvoiceMapHistoryOrder> lockOrderList = xhpcInvoiceMapHistoryOrderMapper.getLockedOnesByHistoryOrderId(historyOrderIds);
        if (lockOrderList.size() > 0) {
            throw new Exception("该历史订单已被其他发票包含");
        }
        //将该发票记录放入数据库生成发票记录,除了所包含的历史订单的总电费，总服务费
        XhpcInvoice xhpcInvoice = new XhpcInvoice();
        xhpcInvoice.setReceiveEmail(saveInvoiceInfoRequest.getReceiveEmail());
        xhpcInvoice.setTitleType(saveInvoiceInfoRequest.getTitleType());
        xhpcInvoice.setTitleContent(saveInvoiceInfoRequest.getTitleContent());
        xhpcInvoice.setDutyNumber(saveInvoiceInfoRequest.getDutyNumber());
        xhpcInvoice.setInvoiceContent(saveInvoiceInfoRequest.getInvoiceContent());
        xhpcInvoice.setInvoiceMoney(saveInvoiceInfoRequest.getInvoiceMoney());
        xhpcInvoice.setFirmAddress(saveInvoiceInfoRequest.getFirmAddress());
        xhpcInvoice.setFirmPhone(saveInvoiceInfoRequest.getFirmPhone());
        xhpcInvoice.setFirmBank(saveInvoiceInfoRequest.getFirmBank());
        xhpcInvoice.setFirmBankAccount(saveInvoiceInfoRequest.getFirmBankAccount());
        xhpcInvoice.setIsShowDate(saveInvoiceInfoRequest.getIsShowDate());
        xhpcInvoice.setUserNotes(saveInvoiceInfoRequest.getUserNotes());
        xhpcInvoice.setCreatorId(saveInvoiceInfoRequest.getCreatorId());
        xhpcInvoice.setCreatorType(saveInvoiceInfoRequest.getCreatorType());
        xhpcInvoice.setCreator(saveInvoiceInfoRequest.getCreator());
        xhpcInvoice.setCreateTime(DateUtils.parseDate(saveInvoiceInfoRequest.getCreateTime()));

        xhpcInvoice.setStatus(0);
        xhpcInvoice.setInvoiceStatus(saveInvoiceInfoRequest.getInvoiceStatus());
        xhpcInvoiceMapper.insertSelectiveAndReturnId(xhpcInvoice);
        //建立订单与发票之间的关联
        List<XhpcHistoryOrder> xhpcHistoryOrderList = xhpcHistoryOrderMapper.findById(historyOrderIds);
        //获取所插入的发票id
        Long invoiceId = xhpcInvoice.getInvoiceId();
        //存储该发票所包含的所有历史订单总电量
        double totalPowerPrice = 0;
        //存储该发票所包含的所有历史订单总服务费
        double totalServicePrice = 0;
        //该变量是用来计算内部存储的历史订单金额是否与传入的一致
        double totalActPrice = 0;
        for (XhpcHistoryOrder xhpcHistoryOrder : xhpcHistoryOrderList) {
            XhpcInvoiceMapHistoryOrder xhpcInvoiceMapHistoryOrder = new XhpcInvoiceMapHistoryOrder();
            xhpcInvoiceMapHistoryOrder.setInvoiceId(invoiceId);
            xhpcInvoiceMapHistoryOrder.setHistoryOrderId(xhpcHistoryOrder.getHistoryOrderId());
            xhpcInvoiceMapHistoryOrder.setHistoryUserId(xhpcHistoryOrder.getUserId());
            xhpcInvoiceMapHistoryOrder.setHistoryUserType(Long.valueOf(xhpcHistoryOrder.getSource()));
            xhpcInvoiceMapHistoryOrder.setHistorySerialNumber(xhpcHistoryOrder.getSerialNumber());
            xhpcInvoiceMapHistoryOrder.setPowerPriceTotal(xhpcHistoryOrder.getPowerPriceTotal());
            xhpcInvoiceMapHistoryOrder.setServicePriceTotal(BigDecimal.valueOf(xhpcHistoryOrder.getServicePriceTotal().doubleValue() - xhpcHistoryOrder.getPromotionDiscount().doubleValue()));
            xhpcInvoiceMapHistoryOrder.setPromotionDiscount(xhpcHistoryOrder.getPromotionDiscount());
            xhpcInvoiceMapHistoryOrder.setHistoryActPrice(xhpcHistoryOrder.getActPrice());
            xhpcInvoiceMapHistoryOrder.setCreateTime(xhpcHistoryOrder.getCreateTime());
            xhpcInvoiceMapHistoryOrder.setChargingMode(xhpcHistoryOrder.getChargingMode());
            xhpcInvoiceMapHistoryOrder.setChargingStationId(xhpcHistoryOrder.getChargingStationId());
            xhpcInvoiceMapHistoryOrder.setTerminalId(xhpcHistoryOrder.getTerminalId());
            xhpcInvoiceMapHistoryOrder.setLockFlag(InvoiceMapHistoryOrderStatusConst.LOCK);
            xhpcInvoiceMapHistoryOrderMapper.insertSelective(xhpcInvoiceMapHistoryOrder);
            totalPowerPrice += xhpcHistoryOrder.getPowerPriceTotal().doubleValue();
            totalServicePrice += (xhpcHistoryOrder.getServicePriceTotal().doubleValue() - xhpcHistoryOrder.getPromotionDiscount().doubleValue());
            totalActPrice += xhpcHistoryOrder.getActPrice().doubleValue();
        }

        BigDecimal bigDecimal = saveInvoiceInfoRequest.getInvoiceMoney().setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal bigDecimal2 = new BigDecimal(totalActPrice).setScale(2, BigDecimal.ROUND_HALF_UP);
        System.out.println("<<<<<<<<<<111<<<<<<<<发票 bigDecimal2>>>>>>>>>>111>>>>>>>>"+bigDecimal2);
        System.out.println("<<<<<<<<<<111<<<<<<<<发票 bigDecimal>>>>>>>>>>111>>>>>>>>"+bigDecimal);
        if (!bigDecimal2.equals(bigDecimal)) {
            throw new Exception("传入的发票金额与实际包含的历史订单总金额参数不匹配");
        }
        xhpcInvoice.setInvoiceOrderEletricTotalMoney(BigDecimal.valueOf(totalPowerPrice));
        xhpcInvoice.setInvoiceOrderServiceTotalMoney(BigDecimal.valueOf(totalServicePrice));
        xhpcInvoiceMapper.updateElectricAndServiceById(xhpcInvoice);
        try {
            LoginUser loginUser = tokenService.getLoginUser();
            getCreatorRead(saveInvoiceInfoRequest.getCreatorId(),saveInvoiceInfoRequest.getCreatorType(),loginUser.getTenantId());
        }catch (Exception e){

        }

    }



    /**
     * 将用户申请的发票信息，保存到数据库中
     *
     * @param saveInvoiceInfoRequest 发票信息
     * @throws Exception 传入发票金额参数与内部该发票所包含的所有订单金额参数不一致出现，出现此异常
     * @author WH
     * @date 2021/12/28 14:33
     * @since version-1.0
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveInvoiceInfo(SaveInvoiceInfoRequest saveInvoiceInfoRequest) throws Exception {
        //判断传入的历史订单是否被其他发票包含
        List<Integer> historyOrderIds = saveInvoiceInfoRequest.getHistoryOrderIds();
        List<XhpcInvoiceMapHistoryOrder> lockOrderList = xhpcInvoiceMapHistoryOrderMapper.getLockedOnesByHistoryOrderId(historyOrderIds);
        if (lockOrderList.size() > 0) {
            throw new Exception("该历史订单已被其他发票包含");
        }

       List<Map<String, Object>> operatorIdList = xhpcHistoryOrderMapper.countOperatorOnHistoryOrderIds(historyOrderIds);

        List<Map<String, Object>> list =new ArrayList<>();
        String operatorNames ="";
        String operatorIds ="";
        for (int i = 0; i <operatorIdList.size() ; i++) {
            Map<String, Object> stringObjectMap = operatorIdList.get(i);
            Map<String, Object> map =new HashMap<>();
            String operatorId = stringObjectMap.get("operatorId").toString();
            int invoiceType = Integer.parseInt(stringObjectMap.get("invoiceType").toString());
            String operatorName = stringObjectMap.get("operatorName").toString();
            if(i==0){
                if(invoiceType==1){
                    operatorNames = operatorName;
                    operatorIds = operatorId;
                }else{
                    map.put("operatorId",stringObjectMap.get("operatorId"));
                    map.put("invoiceType",invoiceType);
                    map.put("operatorName",operatorName);
                    list.add(map);
                }
            }else{
                if(invoiceType==1){
                    operatorNames = operatorNames+","+operatorName;
                    operatorIds = operatorIds+","+operatorId;
                }else{
                    map.put("operatorId",stringObjectMap.get("operatorId"));
                    map.put("invoiceType",invoiceType);
                    map.put("operatorName",operatorName);
                    list.add(map);
                }
            }
        }
        if(!"".equals(operatorNames)){
            Map<String, Object> map =new HashMap<>();
            map.put("operatorId",operatorIds);
            map.put("invoiceType",1);
            map.put("operatorName",operatorNames);
            list.add(map);
        }
        //该变量是用来计算内部存储的历史订单金额是否与传入的一致
        double totalActPrice = 0;
        for (int i = 0; i <list.size() ; i++) {
            Map<String, Object> stringObjectMap = list.get(i);
            String  operatorId = stringObjectMap.get("operatorId").toString();
            Integer invoiceType =1;
            if(operatorId.split(",").length==1){
                invoiceType = Integer.valueOf(stringObjectMap.get("operatorId").toString());
            }

            String  operatorName = stringObjectMap.get("operatorName").toString();
            //将该发票记录放入数据库生成发票记录,除了所包含的历史订单的总电费，总服务费
            XhpcInvoice xhpcInvoice = new XhpcInvoice();
            xhpcInvoice.setReceiveEmail(saveInvoiceInfoRequest.getReceiveEmail());
            xhpcInvoice.setTitleType(saveInvoiceInfoRequest.getTitleType());
            xhpcInvoice.setTitleContent(saveInvoiceInfoRequest.getTitleContent());
            xhpcInvoice.setDutyNumber(saveInvoiceInfoRequest.getDutyNumber());
            xhpcInvoice.setInvoiceContent(saveInvoiceInfoRequest.getInvoiceContent());
            xhpcInvoice.setFirmAddress(saveInvoiceInfoRequest.getFirmAddress());
            xhpcInvoice.setFirmPhone(saveInvoiceInfoRequest.getFirmPhone());
            xhpcInvoice.setFirmBank(saveInvoiceInfoRequest.getFirmBank());
            xhpcInvoice.setFirmBankAccount(saveInvoiceInfoRequest.getFirmBankAccount());
            xhpcInvoice.setIsShowDate(saveInvoiceInfoRequest.getIsShowDate());
            xhpcInvoice.setUserNotes(saveInvoiceInfoRequest.getUserNotes());
            xhpcInvoice.setCreatorId(saveInvoiceInfoRequest.getCreatorId());
            xhpcInvoice.setCreatorType(saveInvoiceInfoRequest.getCreatorType());
            xhpcInvoice.setCreator(saveInvoiceInfoRequest.getCreator());
            xhpcInvoice.setCreateTime(DateUtils.parseDate(saveInvoiceInfoRequest.getCreateTime()));
            xhpcInvoice.setStatus(0);
            xhpcInvoice.setInvoiceMoney(new BigDecimal(1));
            xhpcInvoice.setInvoiceStatus(saveInvoiceInfoRequest.getInvoiceStatus());

            xhpcInvoiceMapper.insertSelectiveAndReturnId(xhpcInvoice);
            //获取所插入的发票id
            Long invoiceId = xhpcInvoice.getInvoiceId();
            //存储该发票所包含的所有历史订单总电量
            double totalPowerPrice = 0;
            //存储该发票所包含的所有历史订单总服务费
            double totalServicePrice = 0;
            //建立订单与发票之间的关联
            List<Map<String, Object>> xhpcHistoryOrderList = xhpcHistoryOrderMapper.findHistoryOrderIds(historyOrderIds, operatorId);

            for (int j = 0; j <xhpcHistoryOrderList.size() ; j++) {

                Map<String, Object> map = xhpcHistoryOrderList.get(j);

                XhpcInvoiceMapHistoryOrder xhpcInvoiceMapHistoryOrder = new XhpcInvoiceMapHistoryOrder();
                xhpcInvoiceMapHistoryOrder.setInvoiceId(invoiceId);
                xhpcInvoiceMapHistoryOrder.setHistoryOrderId(Long.valueOf(map.get("historyOrderId").toString()));
                xhpcInvoiceMapHistoryOrder.setHistoryUserId(Long.valueOf(map.get("userId").toString()));
                xhpcInvoiceMapHistoryOrder.setHistoryUserType(Long.valueOf(map.get("source").toString()));
                xhpcInvoiceMapHistoryOrder.setHistorySerialNumber(map.get("serialNumber").toString());
                xhpcInvoiceMapHistoryOrder.setPowerPriceTotal(new BigDecimal(map.get("powerPriceTotal").toString()));
                xhpcInvoiceMapHistoryOrder.setServicePriceTotal(BigDecimal.valueOf(new BigDecimal(map.get("servicePriceTotal").toString()).doubleValue() - new BigDecimal(map.get("promotionDiscount").toString()).doubleValue()));
                xhpcInvoiceMapHistoryOrder.setPromotionDiscount(new BigDecimal(map.get("promotionDiscount").toString()));
                xhpcInvoiceMapHistoryOrder.setHistoryActPrice(new BigDecimal(map.get("actPrice").toString()));

                if(map.get("createTime").toString().length()==16){
                    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm");
                    LocalDateTime localDateTime = LocalDateTime.parse(map.get("createTime").toString(), dateTimeFormatter);
                    xhpcInvoiceMapHistoryOrder.setCreateTime(Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()));
                }else if(map.get("createTime").toString().length()==19){
                    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
                    LocalDateTime localDateTime = LocalDateTime.parse(map.get("createTime").toString(), dateTimeFormatter);
                    xhpcInvoiceMapHistoryOrder.setCreateTime(Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()));
                }

                xhpcInvoiceMapHistoryOrder.setChargingMode(map.get("chargingMode").toString());
                xhpcInvoiceMapHistoryOrder.setChargingStationId(Long.valueOf(map.get("chargingStationId").toString()));
                xhpcInvoiceMapHistoryOrder.setTerminalId(Long.valueOf(map.get("terminalId").toString()));
                xhpcInvoiceMapHistoryOrder.setLockFlag(InvoiceMapHistoryOrderStatusConst.LOCK);
                xhpcInvoiceMapHistoryOrderMapper.insertSelective(xhpcInvoiceMapHistoryOrder);
                totalPowerPrice += new BigDecimal(map.get("powerPriceTotal").toString()).doubleValue();
                totalServicePrice += (new BigDecimal(map.get("servicePriceTotal").toString()).doubleValue() - new BigDecimal(map.get("promotionDiscount").toString()).doubleValue());
                totalActPrice += new BigDecimal(map.get("actPrice").toString()).doubleValue();

            }
            xhpcInvoice.setInvoiceOrderEletricTotalMoney(BigDecimal.valueOf(totalPowerPrice));
            xhpcInvoice.setInvoiceOrderServiceTotalMoney(BigDecimal.valueOf(totalServicePrice));
            xhpcInvoice.setInvoiceMoney(BigDecimal.valueOf(totalPowerPrice).add(BigDecimal.valueOf(totalServicePrice)));
            if(invoiceType==1){
                xhpcInvoice.setOrderOperatorId(operatorId);
                xhpcInvoice.setInvoiceOperatorId(1L);
                xhpcInvoice.setInvoiceOperatorName(operatorName);
            }else{
                xhpcInvoice.setOrderOperatorId(operatorId);
                xhpcInvoice.setInvoiceOperatorId(Long.valueOf(operatorId));
                xhpcInvoice.setInvoiceOperatorName(operatorName);
            }
            xhpcInvoiceMapper.updateElectricAndServiceById(xhpcInvoice);
        }

            BigDecimal bigDecimal = saveInvoiceInfoRequest.getInvoiceMoney().setScale(2, BigDecimal.ROUND_HALF_UP);
            BigDecimal bigDecimal2 = new BigDecimal(totalActPrice).setScale(2, BigDecimal.ROUND_HALF_UP);
            if (!bigDecimal2.equals(bigDecimal)) {
                throw new Exception("传入的发票金额与实际包含的历史订单总金额参数不匹配");
            }

        try {
            LoginUser loginUser = tokenService.getLoginUser();
            getCreatorRead(saveInvoiceInfoRequest.getCreatorId(),saveInvoiceInfoRequest.getCreatorType(),loginUser.getTenantId());
        }catch (Exception e){

        }

    }




    /**
     * 查询指定用户没有查看的已开的发票的数量，即该用户有几个未读发票
     *
     * @param creatorId   用户id
     * @param creatorType 用户类型
     * @return 未读发票数量
     * @author WH
     * @date 2021/12/28 19:01
     * @since version-1.0
     */
    @Override
    public Long findNotReadCount(Long creatorId, Integer creatorType) {

        return xhpcInvoiceMapper.findNotReadCount(creatorId, creatorType);
    }

    /**
     * 导出所有发票记录（已开与未开）到Excel中
     *
     * @param invoiceIds 发票id
     * @param response   响应对象
     * @author WH
     * @date 2021/12/30 10:16
     * @since version-1.0
     */
    @Override
    public void exportExcel(List<String> invoiceIds, HttpServletResponse response) throws IOException {
        //创建Excel写入对象
        ExcelWriter writer = ExcelUtil.getWriter("record.xlsx");
        //设置单元格标题别名
        setExcelCellName(writer);
        //定义每一行的行号（1，2，3，4...）
        int rowsNumber = 1;
        //设定初始合并行参数（即第一行该从哪行开始合并，合并几行）
        int rowStart = 1;
        int lastRow = 0;
        for (String invoiceId : invoiceIds) {
            List<ExcelInvoiceRow> excelInvoiceRows = xhpcInvoiceMapper.selectExcelInvoiceById(Long.valueOf(invoiceId));
            //往记录中塞入行号
            for (ExcelInvoiceRow excelInvoiceRow : excelInvoiceRows) {
                excelInvoiceRow.setRowsNumber(rowsNumber);
            }
            //写入记录
            writer.write(excelInvoiceRows);
            int invoiceCount = excelInvoiceRows.size();
            //如果写入的发票记录只有一个，就不合并单元格，增加合并行索引，为下面需要合并的行做准备。
            if (invoiceCount == 1) {
                lastRow = lastRow + 1;
                rowStart = rowStart + 1;
            } else {
                //计算每条要合并发票记录的行的最后一个行号
                lastRow = lastRow + invoiceCount;
                //合并单元格
                for (int columnIndex = 0; columnIndex <= 22; columnIndex++) {
                    writer.merge(rowStart, lastRow, columnIndex, columnIndex, null, false);
                }
                //计算每条要合并发票记录的行的第一个行号
                rowStart = rowStart + invoiceCount;
            }
            rowsNumber++;
        }
        //设置文件类型
        response.setContentType(ExcelUtil.XLSX_CONTENT_TYPE);
        //让浏览器下载
        response.addHeader("Content-Disposition", "attachment;filename=" + "invoiceRecord.xlsx"); //设置返回的文件名称
        //写入到Response中
        writer.flush(response.getOutputStream(), true);
                                                                                                                                                                                                                                  }

    /**
     * 查询是否有未开票的订单
     *
     * @return
     */
    @Override
    public int getInvoiceInfo() {
        return xhpcInvoiceMapper.getInvoiceInfo();
    }

    /**
     * 设置生成的Excel表格单元格标题
     *
     * @param writer Excel写入器
     * @author WH
     * @date 2021/12/31 11:10
     * @since version-1.0
     */
    private void setExcelCellName(ExcelWriter writer) {

        writer.addHeaderAlias("rowsNumber", "序号");
        writer.addHeaderAlias("invoiceType", "发票类型");
        writer.addHeaderAlias("receiveEmail", "接收邮箱");
        writer.addHeaderAlias("titleType", "抬头类型");
        writer.addHeaderAlias("titleContent", "抬头内容");
        writer.addHeaderAlias("dutyNumber", "税号");
        writer.addHeaderAlias("invoiceContent", "发票内容");
        writer.addHeaderAlias("invoiceMoney", "发票总金额");
        writer.addHeaderAlias("invoiceOrderElectricTotalMoney", "总电费金额");
        writer.addHeaderAlias("invoiceOrderServiceTotalMoney", "总服务费金额");
        writer.addHeaderAlias("firmAddress", "地址");
        writer.addHeaderAlias("firmPhone", "电话号码");
        writer.addHeaderAlias("firmBank", "开户行");
        writer.addHeaderAlias("firmBankAccount", "银行开户账号");
        writer.addHeaderAlias("isShowDate", "用户是否要求展示交易日期");
        writer.addHeaderAlias("userNotes", "用户备注");
        writer.addHeaderAlias("creatorType", "用户类型");
        writer.addHeaderAlias("iCreateTime", "发票申请时间");
        writer.addHeaderAlias("invoicingTime", "发票开票时间");
        writer.addHeaderAlias("drawer", "开票人");
        writer.addHeaderAlias("financeNotes", "财务备注");
        writer.addHeaderAlias("electricInvoiceUrl", "电子发票地址");
        writer.addHeaderAlias("isRead", "用户是否阅读发票信息");
        writer.addHeaderAlias("historySerialNumber", "订单编号");
        writer.addHeaderAlias("powerPriceTotal", "订单电费");
        writer.addHeaderAlias("servicePriceTotal", "订单服务费");
        writer.addHeaderAlias("promotionDiscount", "折扣费用");
        writer.addHeaderAlias("historyActPrice", "用户实际支付金额");
        writer.addHeaderAlias("hCreateTime", "订单创建时间");
        writer.addHeaderAlias("chargingMode", "订单来源");
    }


    /**
     * 通过发票id查找对应的发票数据
     *
     * @author WH
     * @date 2021/12/20 16:44
     * @since version-1.0
     */
    @Override
    public SpecificInvoiceWrap findSpecificInvoice(Long invoiceId) {

        //处理包装类外层数据
        XhpcInvoice xhpcInvoice = xhpcInvoiceMapper.selectByPrimaryKey(invoiceId);
        SpecificInvoiceWrap specificInvoiceWrap = new SpecificInvoiceWrap();
        BeanUtils.copyProperties(xhpcInvoice, specificInvoiceWrap);
        specificInvoiceWrap.setInvoiceCreateTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, xhpcInvoice.getCreateTime()));
        specificInvoiceWrap.setInvoiceMoney(xhpcInvoice.getInvoiceMoney());
        specificInvoiceWrap.setInvoiceTotalEletricMoney(xhpcInvoice.getInvoiceOrderEletricTotalMoney());
        specificInvoiceWrap.setInvoiceTotalServiceMoney(xhpcInvoice.getInvoiceOrderServiceTotalMoney());
        specificInvoiceWrap.setInvoiceStatus(xhpcInvoice.getInvoiceStatus());
        if (xhpcInvoice.getInvoicingTime() != null) {
            specificInvoiceWrap.setInvoicingTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, xhpcInvoice.getInvoicingTime()));
        }
        //处理包装类内层数据
        specificInvoiceWrap.setHistoryOrders(new SpecificInvoiceWrap.HistoryOrdersDTO());
        SpecificInvoiceWrap.HistoryOrdersDTO historyOrdersDTO = specificInvoiceWrap.getHistoryOrders();
        List<XhpcInvoiceMapHistoryOrder> ordersList = xhpcInvoiceMapHistoryOrderMapper.findOrdersByInvoiceId(xhpcInvoice.getInvoiceId());
        historyOrdersDTO.setTotalItems(Long.valueOf(String.valueOf(ordersList.size())));
        historyOrdersDTO.setHistoryOrdersData(new ArrayList<>());
        List<SpecificInvoiceWrap.HistoryOrdersDTO.HistoryOrdersDataDTO> historyOrdersDataList = historyOrdersDTO.getHistoryOrdersData();
        for (XhpcInvoiceMapHistoryOrder xhpcInvoiceMapHistoryOrder : ordersList) {
            //创建封装历史订单记录的DTO，封装数据
            SpecificInvoiceWrap.HistoryOrdersDTO.HistoryOrdersDataDTO historyOrdersDataDTO = new SpecificInvoiceWrap.HistoryOrdersDTO.HistoryOrdersDataDTO();
            historyOrdersDataDTO.setHistoryOrderId(String.valueOf(xhpcInvoiceMapHistoryOrder.getHistoryOrderId()));
            historyOrdersDataDTO.setActPrice(xhpcInvoiceMapHistoryOrder.getHistoryActPrice());
            historyOrdersDataDTO.setChargingMode(xhpcInvoiceMapHistoryOrder.getChargingMode());
            historyOrdersDataDTO.setHistoryCreateTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, xhpcInvoiceMapHistoryOrder.getCreateTime()));
            historyOrdersDataDTO.setServiceMoney(xhpcInvoiceMapHistoryOrder.getServicePriceTotal());
            historyOrdersDataDTO.setEletricMoney(xhpcInvoiceMapHistoryOrder.getPowerPriceTotal());
            historyOrdersDataDTO.setHistorySerialNumber(xhpcInvoiceMapHistoryOrder.getHistorySerialNumber());
            XhpcChargingStation xhpcChargingStation = xhpcChargingStationMapper.selectXhpcChargingStationById(xhpcInvoiceMapHistoryOrder.getChargingStationId());
            Map<String, Object> operatorInfo = xhpcOperatorMapper.info(xhpcChargingStation.getOperatorId());
            String operatorName = (String) operatorInfo.get("name");
            historyOrdersDataDTO.setOperatorName(operatorName);
            historyOrdersDataList.add(historyOrdersDataDTO);
        }
        //处理historyOrderScope数据
        List<String> historyOrderScope = xhpcInvoiceMapHistoryOrderMapper.getHistoryOrderScopeByInvoiceId(xhpcInvoice.getInvoiceId());
        String minTime = historyOrderScope.get(0);
        String maxTime = historyOrderScope.get(1);
        specificInvoiceWrap.setHistoryOrderScope(minTime + "," + maxTime);
        return specificInvoiceWrap;
    }

    private void getCreatorRead(Long creatorId,Integer creatorType, String tenantId){
        String globalInvoice="global:invoice:"+ tenantId +":";
        String invoice ="";
        if(UserTypeUtil.USER_TYPE.equals(creatorType)){
            invoice =globalInvoice + UserTypeUtil.USER + creatorId;
        }else if(UserTypeUtil.INTERNET_TYPE.equals(creatorType)){
            invoice =globalInvoice + UserTypeUtil.INTERNET + creatorId;
        }else if(UserTypeUtil.COMMUNIT_TYPE.equals(creatorType)){
            invoice =globalInvoice + UserTypeUtil.COMMUNIT + creatorId;
        }else{
            invoice =globalInvoice + UserTypeUtil.CUSTOMERS + creatorId;
        }
        Long notRead =findNotReadCount(creatorId, creatorType);
        redisService.setCacheObject(invoice,notRead);
    }


    public static void main(String[] args) {
        System.out.println("2024-01-02T12:11".length());
        System.out.println("2024-01-02T12:11:00".length());

        Date currentDate = new Date();
        String strTime = DateUtils.parseDateToStr(currentDate);
        System.out.println("strTime"+strTime);

    }

}
