package com.prolog.rdc.tms.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.product.core.framework.util.PlgFxUsrUtils;
import com.prolog.rdc.tms.constant.BmsConstant;
import com.prolog.rdc.tms.dao.mapper.*;
import com.prolog.rdc.tms.model.dto.BmsShipBillFeeDetailDTO;
import com.prolog.rdc.tms.model.dto.SettlementOrderDTO;
import com.prolog.rdc.tms.model.dto.ShipBillFeeListDTO;
import com.prolog.rdc.tms.model.entity.*;
import com.prolog.rdc.tms.model.vo.SettlementOrderUpdateVO;
import com.prolog.rdc.tms.model.vo.ArSettlementQueryVO;
import com.prolog.rdc.tms.service.CloseAccountService;
import com.prolog.rdc.tms.util.ConvertorUtil;
import org.apache.ibatis.plugin.PluginException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class CloseAccountServiceImpl implements CloseAccountService {

    @Autowired
    private BmsShipbillSettlementMapper settlementMapper;
    @Autowired
    private ShipBillFeeDetailMapper feeDetailMapper;
    @Autowired
    private BmsShipbillSettlementDetailMapper settlementDetailMapper;
    @Autowired
    private BmsLogOperationMapper logOperationMapper;
    @Autowired
    private ConvertorUtil convertorUtil;
    @Autowired
    private ShipBillHeadMapper shipBillHeadMapper;
    @Autowired
    private ExpenseManagementMapper managementMapper;
    @Autowired
    private ExpenseAccountMapper expenseAccountMapper;

    @Override
    public Page<SettlementOrderDTO> findList(ArSettlementQueryVO vo) throws ParseException {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        if (!user.getUserType().equals(BmsConstant.USER_TYPE_ZY)) {
            throw new PluginException("仅支持自有账号查询");
        }
        List<SettlementOrderDTO> dtos = Lists.newArrayList();
        Restriction r8;
        Restriction r10 = null;
        Restriction r11 = null;
        Criteria criteria = Criteria.forClass(BmsShipbillSettlementModel.class);
        Restriction r1 = ObjectUtil.isEmpty(vo.getSettlementNo()) ? null : Restrictions.like("settlementNo", "%" + vo.getSettlementNo() + "%");
        Restriction r2 = ObjectUtil.isEmpty(vo.getSettlementName()) ? null : Restrictions.like("settlementName", "%" + vo.getSettlementName() + "%");
        Restriction r3 = ObjectUtil.isEmpty(vo.getSettlementDepartment()) ? null : Restrictions.like("settlementDepartment", "%" + vo.getSettlementDepartment() + "%");
        Restriction r4 = ObjectUtil.isEmpty(vo.getSettlementCompany()) ? null : Restrictions.like("settlementCompany", "%" + vo.getSettlementCompany() + "%");
        vo.setStatus(0);
        Restriction r5 = ObjectUtil.isEmpty(vo.getStatus()) ? null : Restrictions.eq("status", vo.getStatus());
        Restriction r6 = null;
        if (ObjectUtil.isNotEmpty(vo.getCreateStartTime()) && ObjectUtil.isNotEmpty(vo.getCreateEndTime())) {
            r6 = Restrictions.between("createtime", vo.getCreateStartTime() + " 00:00:00", vo.getCreateEndTime() + " 23:59:59");
        }
        // 大于
        if (ObjectUtil.isNotEmpty(vo.getCreateStartTime()) && ObjectUtil.isEmpty(vo.getCreateEndTime())) {
            r6 = Restrictions.gt("createtime", vo.getCreateStartTime() + " 00:00:00");
        }
        // 小于
        if (ObjectUtil.isEmpty(vo.getCreateStartTime()) && ObjectUtil.isNotEmpty(vo.getCreateEndTime())) {
            r6 = Restrictions.le("createtime", vo.getCreateEndTime() + " 23:59:59");
        }
        Restriction r7 = null;
        Restriction r13 = null;
        if (ObjectUtil.isNotEmpty(vo.getUpdateStartTime()) && ObjectUtil.isNotEmpty(vo.getUpdateEndTime())) {
            r7 = Restrictions.between("updatetime", vo.getUpdateStartTime() + " 00:00:00", vo.getUpdateEndTime() + " 23:59:59");
        }
        // 大于
        if (ObjectUtil.isNotEmpty(vo.getUpdateStartTime()) && ObjectUtil.isEmpty(vo.getUpdateEndTime())) {
            r7 = Restrictions.gt("updatetime", vo.getUpdateStartTime() + " 00:00:00");
        }
        // 小于
        if (ObjectUtil.isEmpty(vo.getUpdateStartTime()) && ObjectUtil.isNotEmpty(vo.getUpdateEndTime())) {
            r7 = Restrictions.le("updatetime", vo.getUpdateEndTime() + " 23:59:59");
        }
        if (user.getOwnedAllDataAuthFlag().equals(BmsConstant.USER_DEPARTMENT_AUTH_Y)) {
            r8 = Restrictions.in("settlementDepartmentId", user.getDepts().toArray());
        } else {
            r8 = Restrictions.in("settlementDepartmentId", user.getDepts().toArray());
            r10 = Restrictions.in("settlementCompanyId", user.getConsignors().toArray());
            r11 = Restrictions.in("carrierId", user.getCarriers().toArray());
            r13 = Restrictions.or(r8, r10, r11);
        }
        Restriction r9 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        Restriction r12 = Restrictions.ne("status", 99);
        criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5, r6, r7, r8, r9, r13, r12));
        criteria.setOrder(Order.newInstance().desc("updatetime").desc("createtime"));
        List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[]{
                BmsConstant.CLOSE_ACCOUNT_STATUS, // 结算状态
                BmsConstant.SETTLEMENT_CYCLE // 结算周期
        });
        PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
        List<BmsShipbillSettlementModel> list = settlementMapper.findByCriteria(criteria);
        Map<String, BmsShipBillHeaderModel> shipBillHeaderModelMap = Maps.newHashMap();
        for (BmsShipbillSettlementModel bmsShipbillSettlementModel : list) {
            SettlementOrderDTO settlementOrderDTO = new SettlementOrderDTO();
            BeanUtils.copyProperties(bmsShipbillSettlementModel, settlementOrderDTO);
            settlementOrderDTO.setStatusName(ConvertorUtil.getName(dicData, BmsConstant.CLOSE_ACCOUNT_STATUS, String.valueOf(bmsShipbillSettlementModel.getStatus())));
            settlementOrderDTO.setSettlementCycleName(ConvertorUtil.getName(dicData, BmsConstant.SETTLEMENT_CYCLE, String.valueOf(bmsShipbillSettlementModel.getSettlementCycle())));
            settlementOrderDTO.setTax(bmsShipbillSettlementModel.getTotTax());

            if (shipBillHeaderModelMap.containsKey(bmsShipbillSettlementModel.getShipbillNo())) {
                BmsShipBillHeaderModel existShipbill = shipBillHeaderModelMap.get(bmsShipbillSettlementModel.getShipbillNo());
                settlementOrderDTO.setAffiliationName(existShipbill.getAffiliationName());
                settlementOrderDTO.setCarrierType(existShipbill.getCarrierType());
            } else {
                Criteria criteriaShipBillHeader = Criteria.forClass(BmsShipBillHeaderModel.class);
                Restriction r31 = Restrictions.eq("shipbillNo", bmsShipbillSettlementModel.getShipbillNo());
                criteriaShipBillHeader.setRestriction(Restrictions.and(r31));
                List<BmsShipBillHeaderModel> headerModels = shipBillHeadMapper.findByCriteria(criteriaShipBillHeader);
                if (ObjectUtil.isNotEmpty(headerModels)) {
                    settlementOrderDTO.setAffiliationName(headerModels.get(0).getAffiliationName());
                    settlementOrderDTO.setCarrierType(headerModels.get(0).getCarrierType());
                    shipBillHeaderModelMap.put(headerModels.get(0).getShipbillNo(), headerModels.get(0));
                }
            }
            dtos.add(settlementOrderDTO);
        }
        // 分页设置
        Page<SettlementOrderDTO> page = PageUtils.getPage(dtos);
        if (list instanceof com.github.pagehelper.Page) {
            com.github.pagehelper.Page<BmsShipbillSettlementModel> p0 = (com.github.pagehelper.Page<BmsShipbillSettlementModel>) list;
            page.setPageCount(p0.getPages());
            page.setPageNum(p0.getPageNum());
            page.setPageSize(p0.getPageSize());
            page.setTotalCount(p0.getTotal());
            page.setStartRow(p0.getStartRow());
            page.setEndRow(p0.getEndRow());
        }
        return page;
    }

    @Override
    public SettlementOrderDTO detail(Long id) {
        if (ObjectUtil.isEmpty(id)) {
            throw new PluginException("查询条件不能为空");
        }
        BmsShipbillSettlementModel settlementModel = settlementMapper.findById(id, BmsShipbillSettlementModel.class);
        if (ObjectUtil.isEmpty(settlementModel)) {
            throw new PluginException("查询结算费用信息为空");
        }
        List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[]{
                BmsConstant.SETTLEMENT_CYCLE, // 结算周期
                BmsConstant.CLOSE_ACCOUNT_STATUS, // 结算状态
        });
        SettlementOrderDTO dto = new SettlementOrderDTO();
        BeanUtils.copyProperties(settlementModel, dto);
        dto.setSettlementCycleName(ConvertorUtil.getName(dicData, BmsConstant.SETTLEMENT_CYCLE, String.valueOf(settlementModel.getSettlementCycle())));
        dto.setStatusName(ConvertorUtil.getName(dicData, BmsConstant.CLOSE_ACCOUNT_STATUS, String.valueOf(settlementModel.getStatus())));

        Criteria criteriaShipBillHeader = Criteria.forClass(BmsShipBillHeaderModel.class);
        Restriction r31 = Restrictions.eq("shipbillNo", settlementModel.getShipbillNo());
        criteriaShipBillHeader.setRestriction(Restrictions.and(r31));
        List<BmsShipBillHeaderModel> headerModels = shipBillHeadMapper.findByCriteria(criteriaShipBillHeader);
        if (ObjectUtil.isNotEmpty(headerModels)) {
            dto.setAffiliationName(headerModels.get(0).getAffiliationName());
            dto.setCarrierType(headerModels.get(0).getCarrierType());
        }
        return dto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(SettlementOrderUpdateVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        // 1.判断结算名称是否存在
        Criteria criteria = Criteria.forClass(BmsShipbillSettlementModel.class);
        Restriction r1 = Restrictions.ne("settlementName", vo.getSettlementName());
        Restriction r2 = Restrictions.eq("settlementNo", vo.getSettlementNo());
        Restriction r3 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        criteria.setRestriction(Restrictions.and(r1, r2, r3));
        List<BmsShipbillSettlementModel> models = settlementMapper.findByCriteria(criteria);
        if (ObjectUtil.isNotEmpty(models)) {
            throw new PluginException("结算名称已经存在，请不要重复添加");
        }
        Criteria dcriteria = Criteria.forClass(BmsShipbillSettlementModel.class);
        Restriction r4 = Restrictions.eq("settlementNo", vo.getSettlementNo());
        Restriction r5 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        dcriteria.setRestriction(Restrictions.and(r4, r5));
        List<BmsShipbillSettlementModel> settlementModels = settlementMapper.findByCriteria(dcriteria);
        if (ObjectUtil.isEmpty(settlementModels)) {
            throw new PluginException("获取结算单信息为空");
        }
        Integer status = settlementModels.get(0).getStatus();
        if (0 != status) {
            throw new PluginException("只有草稿状态下的结算单才能修改");
        }
        // 多个费用结算时，判断结算部门，公司，承运商必须相同
        if (vo.getIds().size() > 0) {
            // 查询源费用单
            Criteria sdcriteria = Criteria.forClass(BmsShipbillSettlementDetailModel.class);
            Restriction r6 = Restrictions.eq("settlementNo", vo.getSettlementNo());
            Restriction r7 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
            sdcriteria.setRestriction(Restrictions.and(r6, r7));
            List<BmsShipbillSettlementDetailModel> detailModelList = settlementDetailMapper.findByCriteria(sdcriteria);
            if (ObjectUtil.isEmpty(detailModelList)) {
                throw new PluginException("获取结算单明细信息为空");
            }
            // 新的结算详情
            List<Long> ids = vo.getIds();
            List<BmsShipbillSettlementDetailModel> detailModels = settlementDetailMapper.findByIds(BmsShipbillSettlementDetailModel.class, ids.toArray(), null);
            //  需要知道那个是结算单，那个是费用单
            // 新的费用单
            List<String> newExpenseNoList = detailModels.stream().map(BmsShipbillSettlementDetailModel::getExpenseNo).collect(Collectors.toList());
            // 更新源费用单信息
            List<String> sourceExpenseNoList = detailModelList.stream().map(BmsShipbillSettlementDetailModel::getExpenseNo).collect(Collectors.toList());
            List<String> copySourceExpenseNoList = detailModelList.stream().map(BmsShipbillSettlementDetailModel::getExpenseNo).collect(Collectors.toList());
            List<Long> sourceIds = detailModelList.stream().map(BmsShipbillSettlementDetailModel::getId).collect(Collectors.toList());
            // 获取新增的费用单
            ids.removeAll(sourceIds);
            // 获取删除掉的费用单
            sourceExpenseNoList.removeAll(newExpenseNoList);
            if (ObjectUtil.isNotEmpty(sourceExpenseNoList) && sourceExpenseNoList.size() > 0) {
                // 更新为对账确认
                this.updateSettlement(sourceExpenseNoList, user);
            }
            if (ObjectUtil.isNotEmpty(ids) && ids.size() > 0) {
                List<ShipBillFeeListDTO> feeDetailModels = shipBillHeadMapper.findFeeId(ids);
                for (ShipBillFeeListDTO feeDetailModel : feeDetailModels) {
                    BmsShipbillSettlementDetailModel detailModel = new BmsShipbillSettlementDetailModel();
                    BeanUtils.copyProperties(feeDetailModel, detailModel);
                    detailModels.add(detailModel);

                    Map<String, Object> map = new HashMap<>();
                    map.put("updateperson", user.getNickname());
                    map.put("updatetime", DateUtil.date());
                    map.put("checkStatus", 3);
                    feeDetailMapper.updateMapById(feeDetailModel.getId(), map, BmsShipBillFeeDetailModel.class);
                }
            }
            Map<String, List<BmsShipbillSettlementDetailModel>> departmentMap = detailModels.stream().collect(Collectors.groupingBy(BmsShipbillSettlementDetailModel::getSettlementDepartment));
            if (departmentMap.size() > 1) {
                throw new PluginException("只有相同部门才能一起结算");
            }
            Map<String, List<BmsShipbillSettlementDetailModel>> companyMap = detailModels.stream().collect(Collectors.groupingBy(BmsShipbillSettlementDetailModel::getSettlementCompany));
            if (companyMap.size() > 1) {
                throw new PluginException("只有相同公司才能一起结算");
            }
            Map<String, List<BmsShipbillSettlementDetailModel>> carrierMap = detailModels.stream().collect(Collectors.groupingBy(BmsShipbillSettlementDetailModel::getCarrierCode));
            if (carrierMap.size() > 1) {
                throw new PluginException("只有相同承运商才能一起结算");
            }
            Map<Integer, List<BmsShipbillSettlementDetailModel>> carrierTypeMap = detailModels.stream().collect(Collectors.groupingBy(BmsShipbillSettlementDetailModel::getCarrierType));
            if (carrierTypeMap.size() > 1) {
                throw new PluginException("只有相同承运商类型才能一起结算");
            }

            // 删除源结算单
            Criteria sCriteria = Criteria.forClass(BmsShipbillSettlementDetailModel.class);
            Restriction r10 = Restrictions.in("expenseNo", copySourceExpenseNoList.toArray());
            Restriction r11 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
            sCriteria.setRestriction(Restrictions.and(r10, r11));
            settlementDetailMapper.deleteByCriteria(sCriteria);

            // 更新结算单信息
            BmsShipbillSettlementModel shipbillSettlementModel = settlementModels.get(0);
            BeanUtils.copyProperties(vo, shipbillSettlementModel);
            shipbillSettlementModel.setUpdatetime(DateUtil.date());
            shipbillSettlementModel.setUpdateperson(user.getNickname());
            shipbillSettlementModel.setTotTax(vo.getTaxAmt().subtract(vo.getNoTaxAmt()));
            shipbillSettlementModel.setSettlementCycle(Integer.valueOf(vo.getSettlementCycle()));
            settlementMapper.update(shipbillSettlementModel);

            // 新增结算单
            BmsLogOperationModel logVO = new BmsLogOperationModel();
            logVO.setCreatetime(DateUtil.date());
            logVO.setCreateperson(user.getNickname());
            logVO.setEnterpriseId(user.getEnterpriseId());
            logVO.setEnterpriseName(user.getEnterpriseName());
            logVO.setOrderNo(settlementModels.get(0).getSettlementNo());
            logVO.setLogMemo("结算单修改");
            logVO.setLogType(4);
            logOperationMapper.save(logVO);

            for (BmsShipbillSettlementDetailModel shipBillFeeListDTO : detailModels) {
                BmsShipbillSettlementDetailModel bmsShipbillSettlementModel = new BmsShipbillSettlementDetailModel();
                BeanUtils.copyProperties(shipBillFeeListDTO, bmsShipbillSettlementModel);
                bmsShipbillSettlementModel.setId(null);
                bmsShipbillSettlementModel.setSettlementNo(settlementModels.get(0).getSettlementNo());
                bmsShipbillSettlementModel.setCreateperson(user.getNickname());
                bmsShipbillSettlementModel.setCreatetime(DateUtil.date());
                bmsShipbillSettlementModel.setUpdateperson(user.getNickname());
                bmsShipbillSettlementModel.setUpdatetime(DateUtil.date());
                bmsShipbillSettlementModel.setEnterpriseId(user.getEnterpriseId());
                bmsShipbillSettlementModel.setEnterpriseName(user.getEnterpriseName());
                bmsShipbillSettlementModel.setShipbillNo(shipBillFeeListDTO.getShipbillNo());
                //bmsShipbillSettlementModel.setStatus(120);
                settlementDetailMapper.save(bmsShipbillSettlementModel);
            }
        }
    }

    private void updateSettlement(List<String> sourceExpenseNoList, UserEntity user) {
        for (String expenseNo : sourceExpenseNoList) {
            Criteria criteria = Criteria.forClass(BmsShipBillFeeDetailModel.class);
            Restriction r1 = Restrictions.eq("expenseNo", expenseNo);
            Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
            criteria.setRestriction(Restrictions.and(r1, r2));
            List<BmsShipBillFeeDetailModel> feeDetailModels = feeDetailMapper.findByCriteria(criteria);
            if (ObjectUtil.isEmpty(feeDetailModels)) {
                throw new PluginException("获取费用单信息为空");
            }
            for (BmsShipBillFeeDetailModel feeDetailModel : feeDetailModels) {
                feeDetailModel.setCheckStatus(2);
                feeDetailModel.setUpdatetime(DateUtil.date());
                feeDetailModel.setUpdateperson(user.getNickname());
                feeDetailMapper.update(feeDetailModel);

                // 新增费用单
                BmsLogOperationModel logOperationModel = new BmsLogOperationModel();
                logOperationModel.setCreatetime(DateUtil.date());
                logOperationModel.setCreateperson(user.getNickname());
                logOperationModel.setEnterpriseId(user.getEnterpriseId());
                logOperationModel.setEnterpriseName(user.getEnterpriseName());
                logOperationModel.setOrderNo(feeDetailModel.getExpenseNo());
                logOperationModel.setLogMemo("修改费用单状态对账确认");
                logOperationModel.setLogType(5);
                logOperationMapper.save(logOperationModel);
            }
        }
    }

    @Override
    public void audit(List<Long> ids) {
        if (ObjectUtil.isEmpty(ids)) {
            throw new PluginException("查询条件不能为空");
        }
        Long[] idArr = ids.stream().toArray(Long[]::new);
        List<BmsShipbillSettlementModel> settlementModels = settlementMapper.findByIds(BmsShipbillSettlementModel.class, idArr, null);
        if (ObjectUtil.isEmpty(settlementModels)) {
            throw new PluginException("查询结算费用信息为空");
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        for (BmsShipbillSettlementModel settlementModel : settlementModels) {
            settlementModel.setUpdateperson(user.getNickname());
            settlementModel.setUpdatetime(DateUtil.date());
            settlementModel.setStatus(2);
            settlementMapper.update(settlementModel);

            // 修改费用单状态为结算单审核
            String settlementNo = settlementModel.getSettlementNo();
            Criteria criteria = Criteria.forClass(BmsShipbillSettlementDetailModel.class);
            Restriction r1 = Restrictions.eq("settlementNo", settlementNo);
            criteria.setRestriction(Restrictions.and(r1));
            List<BmsShipbillSettlementDetailModel> detailModelList = settlementDetailMapper.findByCriteria(criteria);
            if (ObjectUtil.isEmpty(detailModelList)) {
                throw new PluginException("查询结算当详情为空");
            }
            for (BmsShipbillSettlementDetailModel settlementDetailModel : detailModelList) {
                // 查询费用单
                Criteria fcriteria = Criteria.forClass(BmsShipBillFeeDetailModel.class);
                Restriction r2 = Restrictions.eq("expenseNo", settlementDetailModel.getExpenseNo());
                Restriction r3 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
                fcriteria.setRestriction(Restrictions.and(r2, r3));
                List<BmsShipBillFeeDetailModel> detailModels = feeDetailMapper.findByCriteria(fcriteria);
                if (ObjectUtil.isEmpty(detailModels)) {
                    throw new PluginException("查询费用单信息为空");
                }
                for (BmsShipBillFeeDetailModel detailModel : detailModels) {
                    detailModel.setUpdateperson(user.getNickname());
                    detailModel.setUpdatetime(DateUtil.date());
                    detailModel.setCheckStatus(4);
                    feeDetailMapper.update(detailModel);

                    // 新增费用单
                    BmsLogOperationModel logOperationModel = new BmsLogOperationModel();
                    logOperationModel.setCreatetime(DateUtil.date());
                    logOperationModel.setCreateperson(user.getNickname());
                    logOperationModel.setEnterpriseId(user.getEnterpriseId());
                    logOperationModel.setEnterpriseName(user.getEnterpriseName());
                    logOperationModel.setOrderNo(detailModel.getExpenseNo());
                    logOperationModel.setLogMemo("更新费用单状态为结算单审核");
                    logOperationModel.setLogType(5);
                    logOperationMapper.save(logOperationModel);
                }
            }

            // 新增结算单
            BmsLogOperationModel logVO = new BmsLogOperationModel();
            logVO.setCreatetime(DateUtil.date());
            logVO.setCreateperson(user.getNickname());
            logVO.setEnterpriseId(user.getEnterpriseId());
            logVO.setEnterpriseName(user.getEnterpriseName());
            logVO.setOrderNo(settlementModel.getSettlementNo());
            logVO.setLogMemo("结算单审核完成");
            logVO.setLogType(4);
            logOperationMapper.save(logVO);
        }
    }

    @Override
    public List<BmsShipBillFeeDetailDTO> feeList(Long id) {
        if (ObjectUtil.isEmpty(id)) {
            throw new PluginException("查询条件不能为空");
        }
        BmsShipbillSettlementModel settlementModel = settlementMapper.findById(id, BmsShipbillSettlementModel.class);
        if (ObjectUtil.isEmpty(settlementModel)) {
            throw new PluginException("查询结算费用信息为空");
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        String settlementNo = settlementModel.getSettlementNo();
        Criteria criteria = Criteria.forClass(BmsShipbillSettlementDetailModel.class);
        Restriction r1 = Restrictions.eq("settlementNo", settlementNo);
        Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        criteria.setRestriction(Restrictions.and(r1, r2));
        criteria.setOrder(Order.newInstance().asc("updatetime"));
        List<BmsShipbillSettlementDetailModel> list = settlementDetailMapper.findByCriteria(criteria);

        List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[]{
                BmsConstant.SHIPBILL_STATUS, // 运单状态
                BmsConstant.SHIPPER_TYPE, // 运输状态
                BmsConstant.ABNORMAL_STATUS, // 异常状态
                BmsConstant.ORDER_TYPE, // 订单类型
                BmsConstant.CONSIGNEE_TYPE, // 收货方类型
                BmsConstant.ORDER_BUSINESS_TYPE, // 订单业务类型
                BmsConstant.SOURCE, // 来源
                BmsConstant.EXPENSE_STATUS, // 费用状态
                BmsConstant.CHECK_STATUS, // 结算状态
                BmsConstant.SETTLEMENT_STATUS,
                BmsConstant.TEMPERATURE_REQUIREMENT// 温度要求
        });
        List<BmsShipBillFeeDetailDTO> detailDTOS = Lists.newArrayList();
        for (BmsShipbillSettlementDetailModel feeDetailModel : list) {
            BmsShipBillFeeDetailDTO dto = new BmsShipBillFeeDetailDTO();
            BeanUtils.copyProperties(feeDetailModel, dto);

            Criteria forClass = Criteria.forClass(BmsExpenseManagementModel.class);
            Restriction r7 = Restrictions.eq("status", 1);
            Restriction r8 = Restrictions.eq("expenseName", feeDetailModel.getExpenseName());
            Restriction r9 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
            forClass.setRestriction(Restrictions.and(r7, r8, r9));
            List<BmsExpenseManagementModel> managementModels = managementMapper.findByCriteria(forClass);
            if (ObjectUtil.isEmpty(managementModels)) {
                throw new PluginException("获取费用信息失败");
            }
            BmsExpenseManagementModel managementModel = managementModels.get(0);

            // 支出，收入
            String expenseAccountCode = managementModel.getExpenseAccountCode();
            Criteria aClass = Criteria.forClass(ExpenseAccountModel.class);
            Restriction r11 = Restrictions.eq("expenseCode", expenseAccountCode);
            Restriction r12 = Restrictions.eq("status", 1);
            aClass.setRestriction(Restrictions.and(r11, r12));
            List<ExpenseAccountModel> mapper = expenseAccountMapper.findByCriteria(aClass);
            if (ObjectUtil.isNotEmpty(mapper)) {
                dto.setExpenseTypeName(Objects.equals(mapper.get(0).getExpenseClassify(), 1) ? "收入" : "支出");
            }

            dto.setBillingStatusName(feeDetailModel.getBillingStatus() == 1 ? "计费成功" : "未计费");
            dto.setExpenseStatusName(ConvertorUtil.getName(dicData, BmsConstant.EXPENSE_STATUS, String.valueOf(feeDetailModel.getCheckStatus())));
            dto.setBillingSourceName(feeDetailModel.getBillingSource() == 1 ? "价格表生成" : "手工录入");
            dto.setCostContract(feeDetailModel.getCostContract());
            dto.setCostDate(feeDetailModel.getCostDate());
            dto.setBillingPrice(feeDetailModel.getCostPriceTable());
            dto.setCostFailReason(feeDetailModel.getCostFailReason());

            dto.setBillingSourceName(feeDetailModel.getBillingSource() == 1 ? "价格表生成" : "手工录入");
            dto.setCheckStatusName(ConvertorUtil.getName(dicData, BmsConstant.CHECK_STATUS, String.valueOf(feeDetailModel.getCheckStatus())));
            dto.setExpenseMemo(feeDetailModel.getMemo());
            dto.setOrderTypeName(ConvertorUtil.getName(dicData, BmsConstant.ORDER_TYPE, String.valueOf(feeDetailModel.getOrderType())));
            dto.setOrderBusinessTypeName(ConvertorUtil.getName(dicData, BmsConstant.ORDER_BUSINESS_TYPE, String.valueOf(feeDetailModel.getOrderBusinessType())));
            dto.setTemperatureRequirementName(ConvertorUtil.getName(dicData, BmsConstant.TEMPERATURE_REQUIREMENT, String.valueOf(feeDetailModel.getTemperatureRequirement())));
            dto.setShipperTypeName(ConvertorUtil.getName(dicData, BmsConstant.SHIPPER_TYPE, String.valueOf(feeDetailModel.getShipperType())));
            dto.setConsigneeTypeName(ConvertorUtil.getName(dicData, BmsConstant.CONSIGNEE_TYPE, String.valueOf(feeDetailModel.getConsigneeType())));
            dto.setDeliveryMethodTypeName(feeDetailModel.getDeliveryMethodType() == 1 ? "配送" : "自提");
            dto.setTransportTypeName(feeDetailModel.getTransportType() == 1 ? "整车" : "零担");
            dto.setSourceName(feeDetailModel.getBillingSource().intValue() == 1 ? "价格表生成" : "手工录入");
            dto.setSettlementStatusName(ConvertorUtil.getName(dicData, BmsConstant.SETTLEMENT_STATUS, String.valueOf(feeDetailModel.getSettlementStatus())));
            dto.setCarrierTypeName(feeDetailModel.getCarrierType() == 1 ? "承运商" : "司机");

            if (feeDetailModel.getCarrierType().intValue() == 2) {
                dto.setCarrierName(feeDetailModel.getDriverName());
            }
            dto.setSettlementCycle(settlementModel.getSettlementCycle());
            detailDTOS.add(dto);
        }
        return detailDTOS;
    }

    @Override
    public List<BmsLogOperationModel> findListForLog(Long id) {
        BmsShipbillSettlementModel settlementModel = settlementMapper.findById(id, BmsShipbillSettlementModel.class);
        if (ObjectUtil.isEmpty(settlementModel)) {
            throw new PluginException("查询结算费用信息为空");
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        Criteria lCriteria = Criteria.forClass(BmsLogOperationModel.class);
        Restriction r1 = Restrictions.eq("orderNo", settlementModel.getSettlementNo());
        Restriction r2 = Restrictions.eq("logType", 4);
        Restriction r3 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        lCriteria.setRestriction(Restrictions.and(r1, r2, r3));
        return logOperationMapper.findByCriteria(lCriteria);
    }

    @Override
    public void invalid(Long id) {
        BmsShipbillSettlementModel settlementModel = settlementMapper.findById(id, BmsShipbillSettlementModel.class);
        if (ObjectUtil.isEmpty(settlementModel)) {
            throw new PluginException("查询结算费用信息为空");
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        settlementModel.setUpdatetime(DateUtil.date());
        settlementModel.setUpdateperson(user.getNickname());
        settlementModel.setStatus(99);
        settlementMapper.update(settlementModel);

        // 新增结算单
        BmsLogOperationModel logVO = new BmsLogOperationModel();
        logVO.setCreatetime(DateUtil.date());
        logVO.setCreateperson(user.getNickname());
        logVO.setEnterpriseId(user.getEnterpriseId());
        logVO.setEnterpriseName(user.getEnterpriseName());
        logVO.setOrderNo(settlementModel.getSettlementNo());
        logVO.setLogMemo("结算单作废");
        logVO.setLogType(4);
        logOperationMapper.save(logVO);

        // 查询结算当详情
        String settlementNo = settlementModel.getSettlementNo();
        Criteria criteria = Criteria.forClass(BmsShipbillSettlementDetailModel.class);
        Restriction r1 = Restrictions.eq("settlementNo", settlementNo);
        criteria.setRestriction(Restrictions.and(r1));
        List<BmsShipbillSettlementDetailModel> detailModelList = settlementDetailMapper.findByCriteria(criteria);
        if (ObjectUtil.isEmpty(detailModelList)) {
            throw new PluginException("查询结算当详情为空");
        }
        for (BmsShipbillSettlementDetailModel settlementDetailModel : detailModelList) {
            // 查询费用单
            Criteria fcriteria = Criteria.forClass(BmsShipBillFeeDetailModel.class);
            Restriction r2 = Restrictions.eq("expenseNo", settlementDetailModel.getExpenseNo());
            Restriction r3 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
            fcriteria.setRestriction(Restrictions.and(r2, r3));
            List<BmsShipBillFeeDetailModel> detailModels = feeDetailMapper.findByCriteria(fcriteria);
            if (ObjectUtil.isEmpty(detailModels)) {
                throw new PluginException("查询费用单信息为空");
            }
            for (BmsShipBillFeeDetailModel detailModel : detailModels) {
                detailModel.setUpdatetime(DateUtil.date());
                detailModel.setUpdateperson(user.getNickname());
                detailModel.setCheckStatus(2);
                feeDetailMapper.update(detailModel);

                // 新增费用单
                BmsLogOperationModel logOperationModel = new BmsLogOperationModel();
                logOperationModel.setCreatetime(DateUtil.date());
                logOperationModel.setCreateperson(user.getNickname());
                logOperationModel.setEnterpriseId(user.getEnterpriseId());
                logOperationModel.setEnterpriseName(user.getEnterpriseName());
                logOperationModel.setOrderNo(detailModel.getExpenseNo());
                logOperationModel.setLogMemo("修改费用单状态对账确认");
                logOperationModel.setLogType(5);
                logOperationMapper.save(logOperationModel);
            }
        }
    }
}