package cn.iocoder.yudao.module.order.service.order.impl;

import cn.iocoder.yudao.framework.apollo.core.event.Order.OrderApprovalTypeCheckEvent;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO;
import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
import cn.iocoder.yudao.framework.i18n.core.I18nMessage;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.service.AbstractService;
import cn.iocoder.yudao.framework.mybatis.core.vo.PageVO;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.bpm.api.BpmCreateServiceFactory;
import cn.iocoder.yudao.module.bpm.enums.WorkFlowEmus;
import cn.iocoder.yudao.module.depository.dal.mysql.warehouse.WarehouseLineMapper;
import cn.iocoder.yudao.module.depository.dto.LogisticsInfoDto;
import cn.iocoder.yudao.module.ecw.dal.dataobject.currency.CurrencyDO;
import cn.iocoder.yudao.module.ecw.service.currency.CurrencyService;
import cn.iocoder.yudao.module.order.convert.order.OrderConvert;
import cn.iocoder.yudao.module.order.convert.orderFeeApplication.OrderFeeApplicationConvert;
import cn.iocoder.yudao.module.order.dal.dataobject.approval.OrderApprovalDO;
import cn.iocoder.yudao.module.order.dal.dataobject.order.OrderDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderFeeApplication.OrderFeeApplicationDO;
import cn.iocoder.yudao.module.order.dal.mysql.orderFeeApplication.OrderFeeApplicationMapper;
import cn.iocoder.yudao.module.order.enums.ApprovalResultStatusEnum;
import cn.iocoder.yudao.module.order.enums.OrderApprovalTypeEnum;
import cn.iocoder.yudao.module.order.enums.OrderApprovalTypeResultEnum;
import cn.iocoder.yudao.module.order.service.approval.OrderApprovalService;
import cn.iocoder.yudao.module.order.service.order.OrderBusinessService;
import cn.iocoder.yudao.module.order.service.order.OrderFeeApplicationService;
import cn.iocoder.yudao.module.order.service.order.OrderQueryService;
import cn.iocoder.yudao.module.order.service.order.OrderService;
import cn.iocoder.yudao.module.order.vo.order.ApplyInfoVO;
import cn.iocoder.yudao.module.order.vo.order.OrderBackVO;
import cn.iocoder.yudao.module.order.vo.orderFeeApplication.*;
import cn.iocoder.yudao.module.product.dto.FeeDto;
import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import cn.iocoder.yudao.module.wealth.dal.dataobject.receivable.ReceivableDO;
import cn.iocoder.yudao.module.wealth.service.receivable.ReceivableService;
import cn.iocoder.yudao.module.wealth.vo.receivable.ReceivableCreateReqVO;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.order.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.order.enums.OrderApprovalTypeEnum.*;

/**
 * 订单费用申请 Service 实现类
 *
 * @author 系统管理员
 */
@Service
@Validated
public class OrderFeeApplicationServiceImpl extends AbstractService<OrderFeeApplicationMapper, OrderFeeApplicationDO> implements OrderFeeApplicationService {

    @Resource
    private OrderFeeApplicationMapper feeApplicationMapper;

    @Resource
    private BpmCreateServiceFactory bpmCreateServiceFactory;

    @Resource
    private ReceivableService receivableService;

    @Resource
    @Lazy
    private OrderService orderService;
    @Resource
    @Lazy
    private OrderBusinessService orderBusinessService;
    @Resource
    @Lazy
    private OrderQueryService orderQueryService;

    @Resource
    private WarehouseLineMapper warehouseLineMapper;

    @Resource
    private AdminUserService adminUserService;

    @Resource
    private CurrencyService currencyService;
    @Resource
    private OrderApprovalService orderApprovalService;
    @Resource
    private ApplicationContext applicationContext;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long createFeeApplication(OrderFeeApplicationCreateReqVO createReqVO) throws Exception {
        //该订单是否有待处理异常或待处理审核则抛出异常
//        orderService.throwPendingExceptionOrProcessingApproval(createReqVO.getOrderId());
        //有未处理的审核单
//        Integer waitApprovalCount = orderService.getAllProcessingApprovalCount(createReqVO.getOrderId());
//        OrderBackVO order = orderService.getOrder(createReqVO.getOrderId());
//        if (waitApprovalCount > 0) {
//            throw exception(ORDER_HAS_PROCESSING_APPROVAL, order.getOrderNo());
//        }

        Long aLong = feeApplicationMapper.selectCount(new LambdaQueryWrapperX<OrderFeeApplicationDO>()
                .eq(OrderFeeApplicationDO::getOrderId, createReqVO.getOrderId())
                .eq(OrderFeeApplicationDO::getStatus, 1));
        if (aLong != null && aLong > 0L) {
            throw exception(ORDER_FEE_APPLICATION_EXIST);
        }
        // 插入
        OrderFeeApplicationDO feeApplication = OrderFeeApplicationConvert.INSTANCE.convert(createReqVO);
        feeApplicationMapper.insert(feeApplication);
        // 返回
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        //创建审批流
        OrderDO orderDO = orderService.selectOne(OrderDO::getOrderId, createReqVO.getOrderId());
        String bpmProcessId = bpmCreateServiceFactory.createBmp(userId, feeApplication.getId(), WorkFlowEmus.ORDER_FREE_APPLY.getKey(), orderDO.getOrderNo(), createReqVO.getCopyUserId());
        orderService.updateStatus(orderDO.getOrderId(), null, null, null, null, null, OrderApprovalTypeResultEnum.expense_apply_processing.getType(), OrderApprovalTypeResultEnum.expense_apply_processing.getDesc());
        feeApplication.setBpmProcessId(bpmProcessId);
        feeApplicationMapper.updateById(feeApplication);
        DictDataRespDTO dictDataFromCache = DictFrameworkUtils.getDictDataFromCache(DictTypeConstants.RECEIVABLE_FEE_TYPE, String.valueOf(createReqVO.getFeeType()));
        CurrencyDO currency = currencyService.getCurrency(createReqVO.getApplicationFeeCurrency());
        List<ApplyInfoVO> list = new ArrayList<>();
        ApplyInfoVO applyInfoVO = new ApplyInfoVO();
        applyInfoVO.setName("申请费用名称");
        applyInfoVO.setNewValue(I18nMessage.getLang() == 0 ? dictDataFromCache.getLabel() : dictDataFromCache.getLabelEn());
        ApplyInfoVO applyInfoVO1 = new ApplyInfoVO();
        applyInfoVO1.setName("金额");
        applyInfoVO1.setNewValue(String.valueOf(createReqVO.getApplicationFee().doubleValue()));
        ApplyInfoVO applyInfoVO2 = new ApplyInfoVO();
        applyInfoVO2.setName("币种");
        applyInfoVO2.setNewValue(I18nMessage.getLang() == 0 ? currency.getTitleZh() : currency.getTitleEn());
        list.add(applyInfoVO);
        list.add(applyInfoVO1);
        list.add(applyInfoVO2);
        orderBusinessService.addOrderOperateLog(createReqVO.getOrderId(), "", "提交费用申请", list);
        return feeApplication.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createFeeBatchApplication(OrderFeeBatchApplicationUpdateReqVO createReqVO) {
//        OrderDO orderDO = orderService.getById(createReqVO.getOrderId());
//        if (orderDO.getAuditType() != 0) {
//            throw exception(ORDER_HAS_PROCESSING_APPROVAL, orderDO.getOrderNo());
//        }
//        LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapperX<OrderApprovalDO>()
//                .eq(OrderApprovalDO::getOrderId, createReqVO.getOrderId())
//                .eq(OrderApprovalDO::getType, expense_apply.getValue())
//                .eq(OrderApprovalDO::getStatus, ApprovalResultStatusEnum.processing.getValue());
//        if (orderApprovalService.count(lambdaQueryWrapper) > 0) {
//            throw exception(ORDER_FEE_APPLICATION_EXIST);
//        }
        OrderApprovalTypeCheckEvent approvalTypeCheckEvent = new OrderApprovalTypeCheckEvent(createReqVO.getOrderId(), null, expense_apply.getValue(), null, false);
        applicationContext.publishEvent(approvalTypeCheckEvent);
        if (approvalTypeCheckEvent.getResult()) {
            throw exception(ORDER_IS_APPROVAL_IN_PROCESS);
        }
        //查询订单信息

        OrderDO orderDO = orderService.getById(createReqVO.getOrderId());
        // 批量转换费用
        List<OrderFeeApplicationUpdateReqVO> baseVOList = createReqVO.getOrderFeeApplicationCreateReqVOList();

        List<OrderFeeApplicationDO> batchFeeList = new ArrayList<>();
        for (OrderFeeApplicationUpdateReqVO vo : baseVOList) {
            OrderFeeApplicationDO feeApplication = OrderFeeApplicationConvert.INSTANCE.convert(vo);
//            if (Objects.isNull(feeApplication.getId())) {
//                feeApplicationMapper.insert(feeApplication);
//            }
            batchFeeList.add(feeApplication);
        }

        //创建审批单，发起流程
        OrderApprovalDO orderApprovalDO = new OrderApprovalDO();
        orderApprovalDO.setFollowUpSalesmanId(String.valueOf(SecurityFrameworkUtils.getLoginUserId()));
        orderApprovalDO.setOrderId(createReqVO.getOrderId());
        //批量费用申请
        orderApprovalDO.setType(expense_apply_BATCH.getValue());
        orderApprovalDO.setStatus(ApprovalResultStatusEnum.processing.getValue());
        orderApprovalDO.setStatus(ApprovalResultStatusEnum.processing.getValue());

        orderApprovalService.save(orderApprovalDO);

        //发起流程
        String formId = bpmCreateServiceFactory.createBmp(SecurityFrameworkUtils.getLoginUserId(),
                orderApprovalDO.getOrderApprovalId(), WorkFlowEmus.ORDER_BATCH_FREE_APPLY.getKey(), orderDO.getOrderNo(), createReqVO.getCopyUserId());
        orderApprovalDO.setFormId(formId);
        List<ApplyInfoVO> list = new ArrayList<>();
        //更新费用列表对应的流程申请ID及状态，并封装审批详情说明文案
        for (OrderFeeApplicationDO feeApplicationDO : batchFeeList) {
            if (feeApplicationDO.isEditMode() || Objects.isNull(feeApplicationDO.getId())) {
                feeApplicationDO.setBatchBpmBusinessId(formId);
                feeApplicationDO.setStatus(ApprovalResultStatusEnum.processing.getValue());
                DictDataRespDTO feeDictDataFromCache = DictFrameworkUtils.getDictDataFromCache(DictTypeConstants.RECEIVABLE_FEE_TYPE, String.valueOf(feeApplicationDO.getFeeType()));
                DictDataRespDTO payDictDataFromCache = DictFrameworkUtils.getDictDataFromCache(DictTypeConstants.PAYMENT_TYPE, String.valueOf(feeApplicationDO.getPayType()));
                CurrencyDO currency = currencyService.getCurrency(feeApplicationDO.getApplicationFeeCurrency());
                String value = "%s: 金额[%s%s], 付款类型[%s]";
                ApplyInfoVO applyInfoVO = new ApplyInfoVO();
                if (Objects.isNull(feeApplicationDO.getId())) {
                    applyInfoVO.setName("新增申请费用");
                    applyInfoVO.setNewValue(String.format(value,
                            I18nMessage.getLang() == 0 ? feeDictDataFromCache.getLabel() : feeDictDataFromCache.getLabelEn() ,
                            feeApplicationDO.getApplicationFee().toString(),
                            I18nMessage.getLang() == 0 ? currency.getTitleZh() : currency.getTitleEn(),
                            I18nMessage.getLang() == 0 ? payDictDataFromCache.getLabel() : payDictDataFromCache.getLabelEn()));
                }else {
                    OrderFeeApplicationDO oldFeeAppliction = feeApplicationMapper.selectById(feeApplicationDO.getId());
                    DictDataRespDTO feeDictDataFromCacheOld = DictFrameworkUtils.getDictDataFromCache(DictTypeConstants.RECEIVABLE_FEE_TYPE, String.valueOf(oldFeeAppliction.getFeeType()));
                    DictDataRespDTO payDictDataFromCacheOld = DictFrameworkUtils.getDictDataFromCache(DictTypeConstants.PAYMENT_TYPE, String.valueOf(oldFeeAppliction.getPayType()));
                    CurrencyDO currencyOld = currencyService.getCurrency(oldFeeAppliction.getApplicationFeeCurrency());
                    applyInfoVO.setName("修改申请费用");
                    applyInfoVO.setNewValue(String.format(value,
                            I18nMessage.getLang() == 0 ? feeDictDataFromCache.getLabel() : feeDictDataFromCache.getLabelEn() ,
                            feeApplicationDO.getApplicationFee().toString(),
                            I18nMessage.getLang() == 0 ? currency.getTitleZh() : currency.getTitleEn(),
                            I18nMessage.getLang() == 0 ? payDictDataFromCache.getLabel() : payDictDataFromCache.getLabelEn()));
                    applyInfoVO.setOrgValue(String.format(value,
                            I18nMessage.getLang() == 0 ? feeDictDataFromCacheOld.getLabel() : feeDictDataFromCacheOld.getLabelEn() ,
                            oldFeeAppliction.getApplicationFee().toString(),
                            I18nMessage.getLang() == 0 ? currencyOld.getTitleZh() : currencyOld.getTitleEn(),
                            I18nMessage.getLang() == 0 ? payDictDataFromCacheOld.getLabel() : payDictDataFromCacheOld.getLabelEn()));
                }
                list.add(applyInfoVO);
            }
        }
        orderApprovalDO.setDetails(JSONObject.toJSONString(batchFeeList));
        orderApprovalService.updateById(orderApprovalDO);

        orderBusinessService.addOrderOperateLog(createReqVO.getOrderId(), "", "提交费用申请", list);
        orderService.updateStatus(orderDO.getOrderId(), null, null, null, null, null, OrderApprovalTypeResultEnum.expense_apply_batch_processing.getType(), OrderApprovalTypeResultEnum.expense_apply_batch_processing.getDesc());


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateFeeApplication(OrderFeeApplicationUpdateReqVO updateReqVO) {
        OrderDO orderDO = orderService.getById(updateReqVO.getOrderId());
        OrderApprovalTypeCheckEvent approvalTypeCheckEvent = new OrderApprovalTypeCheckEvent(updateReqVO.getOrderId(), null, expense_apply.getValue(), null, false);
        applicationContext.publishEvent(approvalTypeCheckEvent);
        if (approvalTypeCheckEvent.getResult()) {
            throw exception(ORDER_HAS_PROCESSING_APPROVAL, orderDO.getOrderNo());
        }
        OrderFeeApplicationDO orderFeeApplicationDOOld = feeApplicationMapper.selectById(updateReqVO.getId());
        // 校验存在
        if (orderFeeApplicationDOOld == null) {
            throw exception(FEE_APPLICATION_NOT_EXISTS);
        }
        // 更新
        OrderFeeApplicationDO updateObj = OrderFeeApplicationConvert.INSTANCE.convert(updateReqVO);
        //创建审批单，发起流程
        OrderApprovalDO orderApprovalDO = new OrderApprovalDO();
        orderApprovalDO.setFollowUpSalesmanId(String.valueOf(SecurityFrameworkUtils.getLoginUserId()));
        orderApprovalDO.setOrderId(updateReqVO.getOrderId());
        //费用申请
        orderApprovalDO.setType(expense_apply.getValue());
        orderApprovalDO.setStatus(ApprovalResultStatusEnum.processing.getValue());
        orderApprovalDO.setDetails(JSONObject.toJSONString(updateObj));
        Long bpmProcessId = orderApprovalService.applyAndCreate(orderApprovalDO, WorkFlowEmus.ORDER_FREE_APPLY, updateReqVO.getCopyUserId());
        Integer auditType = OrderApprovalTypeResultEnum.expense_apply_processing.getType();
        orderService.updateStatus(orderDO.getOrderId(), null, null, null, null, null, auditType, OrderApprovalTypeResultEnum.expense_apply_processing.getDesc());
        orderFeeApplicationDOOld.setBpmProcessId(String.valueOf(bpmProcessId));
        orderFeeApplicationDOOld.setStatus(1);
        feeApplicationMapper.updateById(orderFeeApplicationDOOld);
        DictDataRespDTO feeDictDataFromCacheOld = DictFrameworkUtils.getDictDataFromCache(DictTypeConstants.RECEIVABLE_FEE_TYPE, String.valueOf(orderFeeApplicationDOOld.getFeeType()));
        DictDataRespDTO feeDictDataFromCache = DictFrameworkUtils.getDictDataFromCache(DictTypeConstants.RECEIVABLE_FEE_TYPE, String.valueOf(updateReqVO.getFeeType()));
        DictDataRespDTO payDictDataFromCacheOld = DictFrameworkUtils.getDictDataFromCache(DictTypeConstants.PAYMENT_TYPE, String.valueOf(orderFeeApplicationDOOld.getPayType()));
        DictDataRespDTO payDictDataFromCache = DictFrameworkUtils.getDictDataFromCache(DictTypeConstants.PAYMENT_TYPE, String.valueOf(updateReqVO.getPayType()));
        CurrencyDO currency = currencyService.getCurrency(updateReqVO.getApplicationFeeCurrency());
        CurrencyDO currencyOld = currencyService.getCurrency(orderFeeApplicationDOOld.getApplicationFeeCurrency());
        List<ApplyInfoVO> list = new ArrayList<>();
        ApplyInfoVO applyInfoVO = new ApplyInfoVO();
        applyInfoVO.setName("申请费用名称");
        applyInfoVO.setOrgValue(I18nMessage.getLang() == 0 ? feeDictDataFromCacheOld.getLabel() : feeDictDataFromCacheOld.getLabelEn());
        applyInfoVO.setNewValue(I18nMessage.getLang() == 0 ? feeDictDataFromCache.getLabel() : feeDictDataFromCache.getLabelEn());
        list.add(applyInfoVO);
        applyInfoVO = new ApplyInfoVO();
        applyInfoVO.setName("金额");
        applyInfoVO.setOrgValue(String.valueOf(orderFeeApplicationDOOld.getApplicationFee().doubleValue()));
        applyInfoVO.setNewValue(String.valueOf(updateReqVO.getApplicationFee().doubleValue()));
        list.add(applyInfoVO);
        applyInfoVO = new ApplyInfoVO();
        applyInfoVO.setName("币种");
        applyInfoVO.setOrgValue(I18nMessage.getLang() == 0 ? currencyOld.getTitleZh() : currencyOld.getTitleEn());
        applyInfoVO.setNewValue(I18nMessage.getLang() == 0 ? currency.getTitleZh() : currency.getTitleEn());
        list.add(applyInfoVO);
        applyInfoVO = new ApplyInfoVO();
        applyInfoVO.setName("付款类型");
        applyInfoVO.setOrgValue(I18nMessage.getLang() == 0 ? payDictDataFromCacheOld.getLabel() : payDictDataFromCacheOld.getLabelEn());
        applyInfoVO.setNewValue(I18nMessage.getLang() == 0 ? payDictDataFromCache.getLabel() : payDictDataFromCache.getLabelEn());
        list.add(applyInfoVO);
        orderBusinessService.addOrderOperateLog(updateObj.getOrderId(), "", "费用修改提交审核", list);
    }

    @Override
    public void deleteFeeApplication(Long id) {
        OrderFeeApplicationDO orderFeeApplicationDO = feeApplicationMapper.selectById(id);
        // 校验存在
        if (orderFeeApplicationDO == null) {
            throw exception(FEE_APPLICATION_NOT_EXISTS);
        }
        // 当费用金额为0时，可以不经审批直接删除
        // 判断金额是否为0
        if (orderFeeApplicationDO.getApplicationFee().compareTo(BigDecimal.ZERO) != 0) {
            throw exception(FEE_APPLICATION_NOT_IS_ZERO);
        }
        // 删除可能的应收单
        if (orderFeeApplicationDO.getReceivableId() != null &&
                orderFeeApplicationDO.getReceivableId() > 0) {
            long idTemp = (long) orderFeeApplicationDO.getReceivableId();
            ReceivableDO rDo = receivableService.getReceivable(idTemp);
            if (Objects.nonNull(rDo)) {
                receivableService.removeById(rDo.getId());
            }
        }
        // 删除费用申请记录
        feeApplicationMapper.deleteById(id);
        CurrencyDO currency = currencyService.getCurrency(orderFeeApplicationDO.getApplicationFeeCurrency());
        String currencyName = Objects.nonNull(currency) ? (I18nMessage.getLang() == 0 ? currency.getTitleZh() : currency.getTitleEn()) : (I18nMessage.getLang() == 0 ? "未知" : "NUKNOWN");
        DictDataRespDTO feeTypeDictDataFromCache = DictFrameworkUtils.getDictDataFromCache(DictTypeConstants.RECEIVABLE_FEE_TYPE, String.valueOf(orderFeeApplicationDO.getFeeType()));
        DictDataRespDTO payTypeDictDataFromCache = DictFrameworkUtils.getDictDataFromCache(DictTypeConstants.PAYMENT_TYPE, String.valueOf(orderFeeApplicationDO.getPayType()));
        List<ApplyInfoVO> list = new ArrayList<>();
        ApplyInfoVO applyInfoVO = new ApplyInfoVO();
        applyInfoVO.setName("申请费用名称");
        applyInfoVO.setNewValue(I18nMessage.getLang() == 0 ? feeTypeDictDataFromCache.getLabel() : feeTypeDictDataFromCache.getLabelEn());
        list.add(applyInfoVO);
        applyInfoVO = new ApplyInfoVO();
        applyInfoVO.setName("金额");
        applyInfoVO.setNewValue(String.valueOf(orderFeeApplicationDO.getApplicationFee().doubleValue()));
        list.add(applyInfoVO);
        applyInfoVO = new ApplyInfoVO();
        applyInfoVO.setName("币种");
        applyInfoVO.setNewValue(currencyName);
        list.add(applyInfoVO);
        applyInfoVO = new ApplyInfoVO();
        applyInfoVO.setName("付款类型");
        applyInfoVO.setNewValue(I18nMessage.getLang() == 0 ? payTypeDictDataFromCache.getLabel() : payTypeDictDataFromCache.getLabelEn());
        list.add(applyInfoVO);
        orderBusinessService.addOrderOperateLog(orderFeeApplicationDO.getOrderId(), "订单操作", "费用申请删除", list);
    }

    private void validateFeeApplicationExists(Long id) {
        if (feeApplicationMapper.selectById(id) == null) {
            throw exception(FEE_APPLICATION_NOT_EXISTS);
        }
    }

    @Override
    public OrderFeeApplicationDO getFeeApplication(Long id) {
        return feeApplicationMapper.selectById(id);
    }

    @Override
    public List<OrderFeeApplicationDO> getFeeApplicationList(Collection<Long> ids) {
        return feeApplicationMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<OrderFeeApplicationDO> getFeeApplicationPage(OrderFeeApplicationQueryVO query, PageVO page) {
        return feeApplicationMapper.selectPage(page, query);
    }

    @Override
    public List<OrderFeeApplicationDO> getFeeApplicationList(OrderFeeApplicationQueryVO query) {
        return feeApplicationMapper.selectList(query);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateFeeApproveResult(String id, int result) {
        OrderApprovalDO orderApprovalDO = orderApprovalService.getApproval(Long.parseLong(id));
        if (Objects.isNull(orderApprovalDO)){
            throw exception(ORDER_APPROVAL_INFO_NOT_FIND);
        }
        orderApprovalDO.setStatus(result);
        orderApprovalService.updateById(orderApprovalDO);
        // 这里已经将修改后的内容更新到原数据中去了
        OrderFeeApplicationDO orderFeeApplicationDO = JSONObject.parseObject(orderApprovalDO.getDetails(), OrderFeeApplicationDO.class);
        if (orderFeeApplicationDO != null) {
            List<FeeDto> feeDtos = new ArrayList<>();
            if (result == 2) {
                // 审批通过，更新状态与修改后的数据到数据库
                if (Objects.nonNull(orderFeeApplicationDO.getId())){
                    OrderFeeApplicationDO orgFeeApplicationDO = feeApplicationMapper.selectById(orderFeeApplicationDO.getId());
                    orderFeeApplicationDO.setReceivableId(orgFeeApplicationDO.getReceivableId());
                }
                orderFeeApplicationDO.setStatus(result);
                feeApplicationMapper.updateById(orderFeeApplicationDO);
                OrderBackVO order = orderQueryService.getOrder(orderFeeApplicationDO.getOrderId());
                //生成应收
                DictDataRespDTO dictDto = DictFrameworkUtils.getDictDataFromCache("receivable_fee_type", String.valueOf(orderFeeApplicationDO.getFeeType()));
                //修复应收款记录不存在的BUG,
                //添加应收款记录是否存在的判断
                ReceivableDO rDo = null;
                if (orderFeeApplicationDO.getReceivableId() != null &&
                        orderFeeApplicationDO.getReceivableId() > 0) {
                    long idTemp = (long) orderFeeApplicationDO.getReceivableId();
                    rDo = receivableService.getReceivable(idTemp);
                }
                //end  修复应收款记录不存在的BUG

                if (orderFeeApplicationDO.getReceivableId() != null &&
                        orderFeeApplicationDO.getReceivableId() > 0 &&
                        rDo != null) {
                    ReceivableDO receivableDO = new ReceivableDO();
                    //orderFeeApplicationDO 审批信息关联的应收款ID
                    // 添加的注释
                    receivableDO.setId(Long.valueOf(orderFeeApplicationDO.getReceivableId()));
                    receivableDO.setTitleZh(dictDto.getLabel());
                    receivableDO.setTitleEn(dictDto.getLabelEn());
                    receivableDO.setOrderId(orderFeeApplicationDO.getOrderId());
                    receivableDO.setOrderNo(order.getOrderNo());
                    receivableDO.setTotalAmount(orderFeeApplicationDO.getApplicationFee());
                    receivableDO.setCollectionType(orderFeeApplicationDO.getPayType());
                    receivableDO.setUnitPrice(orderFeeApplicationDO.getApplicationFee());
                    receivableDO.setCurrencyId(Long.valueOf(orderFeeApplicationDO.getApplicationFeeCurrency()));
                    receivableDO.setFeeType(orderFeeApplicationDO.getFeeType());
                    receivableDO.setIsPayAdvance(orderFeeApplicationDO.getPayType() == 4 ? 0 : 1);
                    receivableDO.setState(orderFeeApplicationDO.getReceiveFlag());
                    receivableDO.setPaymentUser(String.valueOf(order.getDrawee() != 3 ? order.getDrawee() : orderQueryService.customDrawee(OrderConvert.INSTANCE.convert(order), orderFeeApplicationDO.getFeeType())));//6待修改
                    receivableDO.setFeeSource(2);
                    receivableDO.setAuthor(orderFeeApplicationDO.getApplicationAuthor());
                    receivableDO.setRemark(orderFeeApplicationDO.getRemarks());
                    //应收款此处报应收款不存在的BUG
                    receivableService.updateReceivableById(receivableDO);
                } else {
                    ReceivableCreateReqVO receivableCreateReqVO =
                            new ReceivableCreateReqVO();
                    receivableCreateReqVO.setTitleZh(dictDto.getLabel());
                    receivableCreateReqVO.setTitleEn(dictDto.getLabelEn());
                    receivableCreateReqVO.setOrderId(orderFeeApplicationDO.getOrderId());
                    receivableCreateReqVO.setOrderNo(order.getOrderNo());
                    receivableCreateReqVO.setTotalAmount(orderFeeApplicationDO.getApplicationFee());
                    receivableCreateReqVO.setUnitPrice(orderFeeApplicationDO.getApplicationFee());
                    receivableCreateReqVO.setCollectionType(orderFeeApplicationDO.getPayType());
                    receivableCreateReqVO.setCurrencyId(Long.valueOf(orderFeeApplicationDO.getApplicationFeeCurrency()));
                    receivableCreateReqVO.setFeeType(orderFeeApplicationDO.getFeeType());
                    receivableCreateReqVO.setIsPayAdvance(orderFeeApplicationDO.getPayType() == 4 ? 0 : 1);
                    receivableCreateReqVO.setState(orderFeeApplicationDO.getReceiveFlag());
                    receivableCreateReqVO.setPaymentUser(String.valueOf(order.getDrawee() != 3 ? order.getDrawee() : orderQueryService.customDrawee(OrderConvert.INSTANCE.convert(order), orderFeeApplicationDO.getFeeType())));//6待修改
                    receivableCreateReqVO.setFeeSource(2);
                    receivableCreateReqVO.setAuthor(orderFeeApplicationDO.getApplicationAuthor());
                    receivableCreateReqVO.setRemark(orderFeeApplicationDO.getRemarks());

                    Long receivableId = receivableService.createReceivable(receivableCreateReqVO);
                    //把创建的应收款信息关联到审批主表中
                    orderFeeApplicationDO.setReceivableId(receivableId.intValue());
                }

                feeApplicationMapper.updateById(orderFeeApplicationDO);
                FeeDto feeDto = new FeeDto();
                feeDto.setFeeType(orderFeeApplicationDO.getFeeType());
                feeDto.setAmount(orderFeeApplicationDO.getApplicationFee());
                feeDto.setCurrencyId(orderFeeApplicationDO.getApplicationFeeCurrency());
                feeDtos.add(feeDto);
                orderService.addOrderOtherFee(orderFeeApplicationDO.getOrderId(), feeDtos);
                orderService.updateStatus(orderFeeApplicationDO.getOrderId(), null, null, null, null, null, 0, OrderApprovalTypeResultEnum.expense_apply_pass.getDesc());
//                orderBusinessService.addOrderOperateLog(orderFeeApplicationDO.getOrderId(),"","提交费用申请成功","");
            } else if (result == 4) {
                feeApplicationMapper.update(null, new LambdaUpdateWrapper<OrderFeeApplicationDO>().set(OrderFeeApplicationDO::getStatus, result).eq(OrderFeeApplicationDO::getId, orderFeeApplicationDO.getId()));
                orderService.updateStatus(orderFeeApplicationDO.getOrderId(), null, null, null, null, null, 0, OrderApprovalTypeResultEnum.expense_apply_cancel.getDesc());
                //bpmCreateServiceFactory.cancelBmpById(SecurityFrameworkUtils.getLoginUserId(),orderFeeApplicationDO.getBpmProcessId(),null);
//                orderBusinessService.addOrderOperateLog(orderFeeApplicationDO.getOrderId(),"","取消费用申请","");
            } else if (result == 3) {
                feeApplicationMapper.update(null, new LambdaUpdateWrapper<OrderFeeApplicationDO>().set(OrderFeeApplicationDO::getStatus, result).eq(OrderFeeApplicationDO::getId, orderFeeApplicationDO.getId()));
                orderService.updateStatus(orderFeeApplicationDO.getOrderId(), null, null, null, null, null, 0, OrderApprovalTypeResultEnum.expense_apply_reject.getDesc());
//                orderBusinessService.addOrderOperateLog(orderFeeApplicationDO.getOrderId(),"","提交费用申请失败","");
            }
        }
    }

    /*
    //result
    1, "处理中",
    2, "通过",
    3, "不通过",
    4, "取消"
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateFeeApproveBatchResult(String id, int result) {
        OrderApprovalDO orderApprovalDO = orderApprovalService.getApproval(Long.parseLong(id));
        if (Objects.isNull(orderApprovalDO)){
            throw exception(ORDER_APPROVAL_INFO_NOT_FIND);
        }
        orderApprovalDO.setStatus(result);
        orderApprovalService.updateById(orderApprovalDO);
        if (result == ApprovalResultStatusEnum.pass.getValue()) {
            List<FeeDto> feeDtos = new ArrayList<>();
            OrderBackVO order = orderQueryService.getOrder(orderApprovalDO.getOrderId());
            List<OrderFeeApplicationDO> batchFeeList = null;
            if (Objects.nonNull(orderApprovalDO.getDetails())){
                batchFeeList = JSONObject.parseArray(orderApprovalDO.getDetails(), OrderFeeApplicationDO.class);
            }else {
                LambdaQueryWrapper<OrderFeeApplicationDO> lambdaQueryWrapper = new LambdaQueryWrapper();
                lambdaQueryWrapper.eq(OrderFeeApplicationDO::getOrderId, orderApprovalDO.getOrderId());
                lambdaQueryWrapper.eq(OrderFeeApplicationDO::getBatchBpmBusinessId, orderApprovalDO.getOrderApprovalId());
                batchFeeList = this.list(lambdaQueryWrapper);
            }
            for (OrderFeeApplicationDO feeApplicationDO : batchFeeList) {
                if (Objects.nonNull(feeApplicationDO.getId())){
                    OrderFeeApplicationDO orgFeeApplicationDO = feeApplicationMapper.selectById(feeApplicationDO.getId());
                    feeApplicationDO.setReceivableId(orgFeeApplicationDO.getReceivableId());
                }
                //生成应收
                DictDataRespDTO dictDto = DictFrameworkUtils.getDictDataFromCache("receivable_fee_type", String.valueOf(feeApplicationDO.getFeeType()));
                if (feeApplicationDO.getReceivableId() != null && feeApplicationDO.getReceivableId() > 0) {
                    ReceivableDO receivableDO = new ReceivableDO();
                    //应收款ID
                    receivableDO.setId(Long.valueOf(feeApplicationDO.getReceivableId()));
                    receivableDO.setTitleZh(dictDto.getLabel());
                    receivableDO.setTitleEn(dictDto.getLabelEn());
                    receivableDO.setOrderId(feeApplicationDO.getOrderId());
                    receivableDO.setOrderNo(order.getOrderNo());
                    receivableDO.setTotalAmount(feeApplicationDO.getApplicationFee());
                    receivableDO.setCollectionType(feeApplicationDO.getPayType());
                    receivableDO.setUnitPrice(feeApplicationDO.getApplicationFee());
                    receivableDO.setCurrencyId(Long.valueOf(feeApplicationDO.getApplicationFeeCurrency()));
                    receivableDO.setFeeType(feeApplicationDO.getFeeType());
                    receivableDO.setIsPayAdvance(feeApplicationDO.getPayType() == 4 ? 0 : 1);
                    receivableDO.setState(feeApplicationDO.getReceiveFlag());
                    receivableDO.setPaymentUser(String.valueOf(order.getDrawee() != 3 ? order.getDrawee() : orderQueryService.customDrawee(OrderConvert.INSTANCE.convert(order), feeApplicationDO.getFeeType())));//6待修改
                    receivableDO.setFeeSource(2);
                    receivableDO.setAuthor(feeApplicationDO.getApplicationAuthor());
                    receivableDO.setRemark(feeApplicationDO.getRemarks());
                    //订单费用申请，是申请付给我们的费用，
                    // 所以要更新应收款信息
                    receivableService.updateReceivableById(receivableDO);
                } else {
                    ReceivableCreateReqVO receivableCreateReqVO = new ReceivableCreateReqVO();
                    receivableCreateReqVO.setTitleZh(dictDto.getLabel());
                    receivableCreateReqVO.setTitleEn(dictDto.getLabelEn());
                    receivableCreateReqVO.setOrderId(feeApplicationDO.getOrderId());
                    receivableCreateReqVO.setOrderNo(order.getOrderNo());
                    receivableCreateReqVO.setTotalAmount(feeApplicationDO.getApplicationFee());
                    receivableCreateReqVO.setUnitPrice(feeApplicationDO.getApplicationFee());
                    receivableCreateReqVO.setCollectionType(feeApplicationDO.getPayType());
                    receivableCreateReqVO.setCurrencyId(Long.valueOf(feeApplicationDO.getApplicationFeeCurrency()));
                    receivableCreateReqVO.setFeeType(feeApplicationDO.getFeeType());
                    receivableCreateReqVO.setIsPayAdvance(feeApplicationDO.getPayType() == 4 ? 0 : 1);
                    receivableCreateReqVO.setState(feeApplicationDO.getReceiveFlag());
                    receivableCreateReqVO.setPaymentUser(String.valueOf(order.getDrawee() != 3 ? order.getDrawee() : orderQueryService.customDrawee(OrderConvert.INSTANCE.convert(order), feeApplicationDO.getFeeType())));//6待修改
                    receivableCreateReqVO.setFeeSource(2);
                    receivableCreateReqVO.setAuthor(feeApplicationDO.getApplicationAuthor());
                    receivableCreateReqVO.setRemark(feeApplicationDO.getRemarks());
                    Long receivableId = receivableService.createReceivable(receivableCreateReqVO);
                    feeApplicationDO.setReceivableId(receivableId.intValue());
                }
                feeApplicationDO.setStatus(result);
                if (Objects.nonNull(feeApplicationDO.getId())){
                    feeApplicationMapper.updateById(feeApplicationDO);
                }else {
                    feeApplicationMapper.insert(feeApplicationDO);
                }
                FeeDto feeDto = new FeeDto();
                feeDto.setFeeType(feeApplicationDO.getFeeType());
                feeDto.setAmount(feeApplicationDO.getApplicationFee());
                feeDto.setCurrencyId(feeApplicationDO.getApplicationFeeCurrency());
                feeDtos.add(feeDto);

            }

            orderService.addOrderOtherFee(orderApprovalDO.getOrderId(), feeDtos);
            orderService.updateStatus(orderApprovalDO.getOrderId(), null, null, null, null, null, 0, OrderApprovalTypeResultEnum.expense_apply_pass.getDesc());
        }

        if (result == ApprovalResultStatusEnum.reject.getValue()) {
            LambdaUpdateWrapper<OrderFeeApplicationDO> lambdaUpdateWrapper = new LambdaUpdateWrapper();
            lambdaUpdateWrapper.eq(OrderFeeApplicationDO::getOrderId, orderApprovalDO.getOrderId());
            lambdaUpdateWrapper.eq(OrderFeeApplicationDO::getBatchBpmBusinessId, orderApprovalDO.getOrderApprovalId());
            lambdaUpdateWrapper.set(OrderFeeApplicationDO::getStatus, ApprovalResultStatusEnum.reject.getValue());
            this.update(lambdaUpdateWrapper);
            orderService.updateStatus(orderApprovalDO.getOrderId(), null, null, null, null, null, 0, OrderApprovalTypeResultEnum.expense_apply_reject.getDesc());
        }

        if (result == ApprovalResultStatusEnum.cancel.getValue()) {
            LambdaQueryWrapper<OrderFeeApplicationDO> lambdaQueryWrapper = new LambdaQueryWrapper();
            lambdaQueryWrapper.eq(OrderFeeApplicationDO::getOrderId, orderApprovalDO.getOrderId());
            lambdaQueryWrapper.eq(OrderFeeApplicationDO::getBatchBpmBusinessId, orderApprovalDO.getOrderApprovalId());
            this.remove(lambdaQueryWrapper);
            orderService.updateStatus(orderApprovalDO.getOrderId(), null, null, null, null, null, 0, OrderApprovalTypeResultEnum.expense_apply_cancel.getDesc());
        }
    }

    @Override
    public List<OrderFeeApplicationDO> getFeeApplicationListByOrderId(Long orderId) {
        OrderApprovalDO approvalDO = orderApprovalService.getOne(new LambdaQueryWrapper<OrderApprovalDO>()
                .eq(OrderApprovalDO::getOrderId, orderId)
                .eq(OrderApprovalDO::getStatus, 1)
                .orderByDesc(OrderApprovalDO::getOrderApprovalId).last("limit 1"));
        if (Objects.nonNull(approvalDO) && approvalDO.getType() == 41 && Objects.nonNull(approvalDO.getDetails())) {
            // 对于批量审批中的费用申请，直接返回审批中数据即可
            return JSONObject.parseArray(approvalDO.getDetails(), OrderFeeApplicationDO.class);
        }
        List<OrderFeeApplicationDO> feeApplicationList = feeApplicationMapper.getFeeApplicationListByOrderId(orderId);
        feeApplicationList.stream().forEach(item -> {
            item.setApplicationAuthor(adminUserService.getUser(Long.valueOf(item.getCreator())).getUsername());
            if (item.getReceivableId() != null && item.getReceivableId() != 0) {
                ReceivableDO receivable = receivableService.getReceivable(Long.valueOf(item.getReceivableId()));
                if (receivable != null) {
                    item.setReceiveFlag(receivable.getState());
                } else {
                    item.setReceiveFlag(0);
                }
            } else {
                item.setReceiveFlag(0);
            }
            if (item.getStatus() == 1 && StringUtils.isNotBlank(item.getBpmProcessId())){
               if (Objects.nonNull(approvalDO) && Objects.nonNull(approvalDO.getDetails())){
                   OrderFeeApplicationDO feeApplicationDO = JSONObject.parseObject(approvalDO.getDetails(), OrderFeeApplicationDO.class);
                   BeanUtils.copyProperties(feeApplicationDO, item);
               }
            }
        });
        return feeApplicationList;
    }

    @Override
    public OrderFeeApplicationBackVO getOrderByProcessId(String processId) {
        OrderApprovalDO orderApprovalDO = orderApprovalService.getOne(new LambdaQueryWrapper<OrderApprovalDO>().eq(OrderApprovalDO::getFormId, processId).orderByDesc(OrderApprovalDO::getOrderApprovalId).last("limit 1"));
        if (Objects.nonNull(orderApprovalDO) && orderApprovalDO.getType() == 12 && StringUtils.isNotBlank(orderApprovalDO.getDetails())) {
            OrderFeeApplicationDO orderFeeApplicationDO = JSONObject.parseObject(orderApprovalDO.getDetails(), OrderFeeApplicationDO.class);
            OrderFeeApplicationBackVO convert = OrderFeeApplicationConvert.INSTANCE.convert(orderFeeApplicationDO);
            if (orderFeeApplicationDO != null) {
                OrderBackVO order = orderQueryService.getOrder(orderFeeApplicationDO.getOrderId());
                LogisticsInfoDto startInfoAndDestInfoByLineId = warehouseLineMapper.getStartInfoAndDestInfoByLineId(order.getLineId());
                convert.setStartWarehouse(startInfoAndDestInfoByLineId.getStartTitleZh());
                convert.setDestWarehouse(startInfoAndDestInfoByLineId.getDestTitleZh());
                convert.setOrderBackVO(order);
            }
            return convert;
        }else {
            OrderFeeApplicationDO orderFeeApplicationDO = feeApplicationMapper.selectOne(OrderFeeApplicationDO::getBpmProcessId, processId);
            OrderFeeApplicationBackVO convert = OrderFeeApplicationConvert.INSTANCE.convert(orderFeeApplicationDO);
            if (orderFeeApplicationDO != null) {
                OrderBackVO order = orderQueryService.getOrder(orderFeeApplicationDO.getOrderId());
                LogisticsInfoDto startInfoAndDestInfoByLineId = warehouseLineMapper.getStartInfoAndDestInfoByLineId(order.getLineId());
                convert.setStartWarehouse(startInfoAndDestInfoByLineId.getStartTitleZh());
                convert.setDestWarehouse(startInfoAndDestInfoByLineId.getDestTitleZh());
                convert.setOrderBackVO(order);
            }
            return convert;
        }
    }

    @Override
    public List<OrderFeeApplicationBackVO> getBatchFeeByProcessId(String processId) {
        OrderApprovalDO orderApprovalDO = orderApprovalService.getApproval(Long.valueOf(processId));
        if (Objects.nonNull(orderApprovalDO) && orderApprovalDO.getType() == 41 && StringUtils.isNotBlank(orderApprovalDO.getDetails())) {
            List<OrderFeeApplicationDO> orderFeeApplicationDOList = JSONObject.parseArray(orderApprovalDO.getDetails(), OrderFeeApplicationDO.class);
            return OrderFeeApplicationConvert.INSTANCE.convertList(orderFeeApplicationDOList.stream().filter(fee -> Objects.isNull(fee.getId()) || fee.isEditMode()).collect(Collectors.toList()));
        }else {
            List<OrderFeeApplicationDO> orderFeeApplicationDOList = feeApplicationMapper.selectList(OrderFeeApplicationDO::getBatchBpmBusinessId, processId);
            return OrderFeeApplicationConvert.INSTANCE.convertList(orderFeeApplicationDOList);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelFeeApplication(OrderFeeApplicationUpdateReqVO orderFeeApplicationUpdateReqVO) {
        //只管取消,这些东西应该在回调里面处理
        //OrderFeeApplicationDO orderFeeApplicationDO = feeApplicationMapper.selectOne(OrderFeeApplicationDO::getBpmProcessId, orderFeeApplicationUpdateReqVO.getBpmProcessId());
        //feeApplicationMapper.delete(new LambdaQueryWrapperX<OrderFeeApplicationDO>().eq(OrderFeeApplicationDO::getBpmProcessId, orderFeeApplicationUpdateReqVO.getBpmProcessId()));
        bpmCreateServiceFactory.cancelBmpById(SecurityFrameworkUtils.getLoginUserId(), orderFeeApplicationUpdateReqVO.getBpmProcessId(), orderFeeApplicationUpdateReqVO.getHuifu());
        //Integer auditType = OrderApprovalTypeResultEnum.expense_apply_cancel.getType();
        //orderService.updateStatus(orderFeeApplicationDO.getOrderId(), null, null, null, null, null, 0, OrderApprovalTypeResultEnum.expense_apply_cancel.getDesc());
//        orderBusinessService.addOrderOperateLog(orderFeeApplicationUpdateReqVO.getOrderId(),"","取消费用申请","");
    }

    @Override
    public OrderFeeApplicationBackVO getApprovalFeeApplication(Long id) {
        OrderApprovalDO orderApprovalDO = orderApprovalService.getApproval(id);
        if (Objects.isNull(orderApprovalDO)){
            throw exception(ORDER_APPROVAL_INFO_NOT_FIND);
        }
        // 这里已经将修改后的内容更新到原数据中去了
        OrderFeeApplicationDO orderFeeApplicationDO = JSONObject.parseObject(orderApprovalDO.getDetails(), OrderFeeApplicationDO.class);
        orderFeeApplicationDO.setBpmProcessId(orderApprovalDO.getFormId());
        OrderFeeApplicationBackVO convert = OrderFeeApplicationConvert.INSTANCE.convert(orderFeeApplicationDO);
        if (orderFeeApplicationDO != null) {
            OrderBackVO order = orderQueryService.getOrder(orderFeeApplicationDO.getOrderId());
            LogisticsInfoDto startInfoAndDestInfoByLineId = warehouseLineMapper.getStartInfoAndDestInfoByLineId(order.getLineId());
            convert.setStartWarehouse(startInfoAndDestInfoByLineId.getStartTitleZh());
            convert.setDestWarehouse(startInfoAndDestInfoByLineId.getDestTitleZh());
            convert.setOrderBackVO(order);
        }
        return convert;
    }
}
