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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.apollo.core.event.Order.OrderApprovalTypeCheckEvent;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.spring.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.excel.handler.WaterMarkHandler;
import cn.iocoder.yudao.framework.i18n.core.I18nMessage;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import cn.iocoder.yudao.framework.mybatis.core.vo.PageVO;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.customer.dal.dataobject.customer.CustomerDO;
import cn.iocoder.yudao.module.customer.service.customer.CustomerService;
import cn.iocoder.yudao.module.customer.service.customerContacts.CustomerContactsService;
import cn.iocoder.yudao.module.customer.service.zhongPao.ZhongPaoService;
import cn.iocoder.yudao.module.customer.vo.zhongPao.CustomerZhongPaoQueryVO;
import cn.iocoder.yudao.module.customer.vo.zhongPao.ZhongPaoBestVO;
import cn.iocoder.yudao.module.depository.dal.mysql.warehouse.WarehouseLineMapper;
import cn.iocoder.yudao.module.depository.dal.mysql.warehouse.WarehouseMapper;
import cn.iocoder.yudao.module.depository.dto.LogisticsInfoDto;
import cn.iocoder.yudao.module.depository.vo.warehouse.WarehouseRegionVO;
import cn.iocoder.yudao.module.ecw.api.currency.CurrencyApi;
import cn.iocoder.yudao.module.ecw.api.currency.dto.CurrencyRespDTO;
import cn.iocoder.yudao.module.ecw.api.currency.dto.ExchangeRateRespDTO;
import cn.iocoder.yudao.module.ecw.dal.dataobject.region.RegionDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
import cn.iocoder.yudao.module.infra.service.file.FileService;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.UserRespDTO;
import cn.iocoder.yudao.module.member.dal.dataobject.userCardAuth.UserCardAuthDO;
import cn.iocoder.yudao.module.member.dal.dataobject.userEnterpriseAuth.UserEnterpriseAuthDO;
import cn.iocoder.yudao.module.member.service.userCardAuth.UserCardAuthService;
import cn.iocoder.yudao.module.member.service.userEnterpriseAuth.UserEnterpriseAuthService;
import cn.iocoder.yudao.module.order.convert.order.OrderConvert;
import cn.iocoder.yudao.module.order.convert.orderConsignee.OrderConsigneeConvert;
import cn.iocoder.yudao.module.order.convert.orderConsignor.OrderConsignorConvert;
import cn.iocoder.yudao.module.order.convert.orderDeparture.OrderDepartureConvert;
import cn.iocoder.yudao.module.order.convert.orderItem.OrderItemConvert;
import cn.iocoder.yudao.module.order.convert.orderObjective.OrderObjectiveConvert;
import cn.iocoder.yudao.module.order.convert.orderTime.OrderTimeConvert;
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.orderConsignee.OrderConsigneeDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderConsignor.OrderConsignorDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderDeparture.OrderDepartureDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderException.OrderExceptionDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderItem.OrderItemDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderObjective.OrderObjectiveDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderTime.OrderTimeDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderWarehouseIn.OrderWarehouseInDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderWarehousePicture.OrderWarehousePictureDO;
import cn.iocoder.yudao.module.order.dal.mysql.approval.OrderApprovalMapper;
import cn.iocoder.yudao.module.order.dal.mysql.order.OrderMapper;
import cn.iocoder.yudao.module.order.dal.mysql.orderItem.OrderItemMapper;
import cn.iocoder.yudao.module.order.dal.mysql.orderTime.OrderTimeMapper;
import cn.iocoder.yudao.module.order.dal.mysql.orderWarehouseIn.OrderWarehouseInMapper;
import cn.iocoder.yudao.module.order.dto.*;
import cn.iocoder.yudao.module.order.enums.CustomDraweeEnum;
import cn.iocoder.yudao.module.order.enums.OrderApprovalTypeEnum;
import cn.iocoder.yudao.module.order.enums.OrderExceptionEnum;
import cn.iocoder.yudao.module.order.enums.TransportTypeShortEnum;
import cn.iocoder.yudao.module.order.service.order.*;
import cn.iocoder.yudao.module.order.service.orderException.OrderExceptionService;
import cn.iocoder.yudao.module.order.service.orderWarehouseIn.OrderWarehouseInService;
import cn.iocoder.yudao.module.order.service.orderWarehousePicture.OrderWarehousePictureService;
import cn.iocoder.yudao.module.order.vo.approval.OrderApprovalHeadBaseVO;
import cn.iocoder.yudao.module.order.vo.approval.OrderSpecialApplyVO;
import cn.iocoder.yudao.module.order.vo.approval.OrderSpecialBatchApplyOrderItemDetailVO;
import cn.iocoder.yudao.module.order.vo.approval.OrderSpecialBatchApplyVO;
import cn.iocoder.yudao.module.order.vo.order.*;
import cn.iocoder.yudao.module.order.vo.orderConsignee.OrderConsigneeBackVO;
import cn.iocoder.yudao.module.order.vo.orderException.ExceptionTypeResultVO;
import cn.iocoder.yudao.module.order.vo.orderException.OrderExceptionStatisticsExcelVo;
import cn.iocoder.yudao.module.order.vo.orderException.OrderFeeDetailBackVO;
import cn.iocoder.yudao.module.order.vo.orderItem.OrderItemBackVO;
import cn.iocoder.yudao.module.order.vo.orderLocation.OrderLocationMergeVO;
import cn.iocoder.yudao.module.order.vo.orderWarehouseAdjust.OrderWarehouseAdjustBatchApplyBackVO;
import cn.iocoder.yudao.module.product.vo.coupon.CouponInfoVO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.system.framework.ue.UeProperties;
import cn.iocoder.yudao.module.wealth.dal.dataobject.receipt.ReceiptDO;
import cn.iocoder.yudao.module.wealth.dal.dataobject.receivable.ReceivableDO;
import cn.iocoder.yudao.module.wealth.service.receipt.ReceiptService;
import cn.iocoder.yudao.module.wealth.service.receivable.ReceivableService;
import cn.iocoder.yudao.module.wealth.vo.receivable.ReceivableBackVO;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.excel.constant.ExportConstant.*;
import static cn.iocoder.yudao.module.order.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.order.enums.OrderApprovalTypeEnum.ORDER_UPDATE;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.NOT_FIND_CURRENCY;

/**
 * 订单 Service 实现类
 *
 * @author 系统管理员
 */
@Service
@Validated
@AllArgsConstructor
@Slf4j
public class OrderQueryServiceImpl implements OrderQueryService {

    private final OrderMapper orderMapper;
    private final OrderItemMapper orderItemMapper;
    private final OrderTimeMapper orderTimeMapper;
    private final OrderDepartureService orderDepartureService;
    private final OrderObjectiveService orderObjectiveService;
    private final OrderConsignorService orderConsignorService;
    private final OrderConsigneeService orderConsigneeService;
    private final WarehouseLineMapper warehouseLineMapper;
    private final WarehouseMapper warehouseMapper;
    private final CustomerService customerService;
    private final ZhongPaoService zhongPaoService;
    private final OrderApprovalMapper orderApprovalMapper;
    private final ReceivableService receivableService;
    private final MemberUserApi memberUserApi;
    private final AdminUserApi adminUserApi;
    private final ReceiptService receiptService;
    private final CurrencyApi currencyApi;
    private final ApplicationContext applicationContext;

    private final UserCardAuthService userCardAuthService;

    private final UserEnterpriseAuthService userEnterpriseAuthService;

    private final OrderWarehousePictureService orderWarehousePictureService;


    private final OrderWarehouseInMapper orderWarehouseInMapper;

    private final OrderWarehouseInService orderWarehouseInService;

    private final CustomerContactsService customerContactsService;
    private final OrderExceptionService orderExceptionService;


    private UeProperties ueProperties;
    private FileService fileService;

    @Override
    public OrderBackVO getUpdateOrderApplyInfo(Long orderId, boolean isResubmit) {
        OrderApprovalDO orderApprovalDO = orderApprovalMapper.newOrderCargoControlPickInfo(orderId, null, ORDER_UPDATE.getValue());
        OrderBackVO vo = this.getOrder(orderId);
        if (Objects.nonNull(orderApprovalDO) && 1 == orderApprovalDO.getStatus()) {
            OrderBackVO newVO = JSONObject.parseObject(orderApprovalDO.getDetails(), OrderBackVO.class);
            vo.setFormId(orderApprovalDO.getFormId());
            vo.setOrderApprovalId(orderApprovalDO.getOrderApprovalId());
            vo.setApplyType(orderApprovalDO.getType());
            vo.setApplyStatus(orderApprovalDO.getStatus());
            vo.setApplyInfoList(newVO.getApplyInfoList());
        } else {
            vo.setApplyType(ORDER_UPDATE.getValue());
        }
        if (Objects.nonNull(vo.getConsignorVO())) {
            CustomerDO customerDO = customerService.getCustomer(vo.getConsignorVO().getCustomerId());
            if (Objects.nonNull(customerDO)) {
                vo.setNoConsignee(customerDO.getNoConsignee());
            }
        }
        return vo;
    }


    @Override
    public OrderBackVO getUpdateOrderApplyInfo(Long orderApprovalId) {
        OrderApprovalDO orderApprovalDO = orderApprovalMapper.selectById(orderApprovalId);
        if (!Objects.equals(orderApprovalDO.getType(), ORDER_UPDATE.getValue())) {
            throw exception(ORDER_APPROVAL_INFO_NOT_FIND);
        }
        OrderBackVO vo = JSONObject.parseObject(orderApprovalDO.getDetails(), OrderBackVO.class);
        vo.setFormId(orderApprovalDO.getFormId());
        vo.setOrderApprovalId(orderApprovalDO.getOrderApprovalId());
        vo.setApplyType(orderApprovalDO.getType());
        if (Objects.isNull(vo.getLogisticsInfoDto())) {
            // 物流信息查询
            LogisticsInfoDto logisticsInfoDto = warehouseLineMapper.getStartInfoAndDestInfoByLineId(vo.getLineId());
            if (Objects.isNull(logisticsInfoDto)) {
                throw exception(NOT_FIND_LOGISTICS_INFO);
            }
            logisticsInfoDto.setLineId(vo.getLineId());
            logisticsInfoDto.setTransportId(vo.getTransportId());
            logisticsInfoDto.setChannelId(vo.getChannelId());
            vo.setLogisticsInfoDto(logisticsInfoDto);
        }
//        if (vo.getOrderNo().startsWith("DRAFT")) {
//            vo.setOrderNo("");
//        }
        return vo;
    }

    public Integer customDrawee(OrderDO orderDO, Integer feeType) {
        Integer drawee = 1;
        CustomDraweeEnum customDraweeEnum = CustomDraweeEnum.valueOf(feeType);
        if (Objects.isNull(customDraweeEnum)) {
            return drawee;
        }
        if (StringUtils.isNotBlank(orderDO.getCustomDrawee())) {
            List<CustomDraweeVO> list = JSONObject.parseArray(orderDO.getCustomDrawee(), CustomDraweeVO.class);
            for (CustomDraweeVO customDraweeVO : list) {
                if (Objects.equals(customDraweeVO.getName(), customDraweeEnum.getKey())) {
                    return customDraweeVO.getValue();
                }
            }
        }
        return drawee;
    }

    @Override
    public OrderApprovalHeadBaseVO getOrderApprovalHeadInfo(Long orderId) {
        OrderDO orderDO = orderMapper.headBaseInfo(orderId, I18nMessage.getLang());
        if (Objects.isNull(orderDO)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        // 物流信息查询
        LogisticsInfoDto logisticsInfoDto = warehouseLineMapper.getStartInfoAndDestInfoByLineId(orderDO.getLineId());
        if (Objects.isNull(logisticsInfoDto)) {
            throw exception(NOT_FIND_LOGISTICS_INFO);
        }
        // 始发城市与目的城市
        OrderApprovalHeadBaseVO baseVO = new OrderApprovalHeadBaseVO();
        BeanUtils.copyProperties(logisticsInfoDto, baseVO);
        baseVO.setLineId(orderDO.getLineId());
        baseVO.setTransportId(orderDO.getTransportId());
        baseVO.setChannelId(orderDO.getChannelId());
        baseVO.setOrderNo(orderDO.getOrderNo());
        baseVO.setStatus(orderDO.getStatus());
        baseVO.setAbnormalState(orderDO.getAbnormalState());
        baseVO.setInWarehouseState(orderDO.getInWarehouseState());
        baseVO.setShipmentState(orderDO.getShipmentState());
        baseVO.setDepartureId(orderDO.getDepartureId());
        baseVO.setDepartureName(orderDO.getDepartureName());
        baseVO.setObjectiveId(orderDO.getObjectiveId());
        baseVO.setObjectiveName(orderDO.getObjectiveName());
        return baseVO;
    }


    @Override
    public OrderSpecialApplyVO approvalOrderSpecial(Long approveId) {
        OrderApprovalDO orderApprovalDO = orderApprovalMapper.selectById(approveId);
        if (Objects.isNull(orderApprovalDO)) {
            throw exception(ORDER_APPROVAL_INFO_NOT_FIND);
        } else {
            OrderSpecialApplyVO vo = JSONObject.parseObject(orderApprovalDO.getDetails(), OrderSpecialApplyVO.class);
            vo.setFormId(orderApprovalDO.getFormId());
            vo.setOrderApprovalId(orderApprovalDO.getOrderApprovalId());
            return vo;
        }
    }

    @Override
    public OrderSpecialBatchApplyVO approvalOrderSpecialBatch(Long approveId) {
        OrderApprovalDO orderApprovalDO = orderApprovalMapper.selectById(approveId);
        if (Objects.isNull(orderApprovalDO)) {
            throw exception(ORDER_APPROVAL_INFO_NOT_FIND);
        } else {
            OrderSpecialBatchApplyVO vo = JSONObject.parseObject(orderApprovalDO.getDetails(), OrderSpecialBatchApplyVO.class);
            vo.setFormId(orderApprovalDO.getFormId());
            vo.setOrderApprovalId(orderApprovalDO.getOrderApprovalId());
            return vo;
        }
    }

    @Override
    public OrderSpecialApplyVO approvalOrderSpecialByOrderItemId(Long orderId, Long orderItemId, Integer type,
                                                                 boolean isResubmit) {
        OrderSpecialApplyVO vo;
        OrderApprovalDO orderApprovalDO = orderApprovalMapper.newItemInfo(orderItemId, orderId, type);
        OrderApprovalHeadBaseVO baseVO = this.getOrderApprovalHeadInfo(orderId);
        isResubmit = Objects.isNull(orderApprovalDO) || 1 != orderApprovalDO.getStatus();
        if (Objects.nonNull(orderApprovalDO) && !isResubmit) {
            vo = JSONObject.parseObject(orderApprovalDO.getDetails(), OrderSpecialApplyVO.class);
            vo.setOrderApprovalHeadBaseVO(baseVO);
            vo.setFormId(orderApprovalDO.getFormId());
            vo.setOrderApprovalId(orderApprovalDO.getOrderApprovalId());
            return vo;
        }
        if (type == 1 || type == 2 || type == 3) {
            OrderItemDO orderItemDO = orderItemMapper.selectById(orderItemId);
            if (Objects.isNull(orderItemDO)) {
                throw exception(ORDER_ITEM_PROD_NOT_EXISTS);
            }
            vo = new OrderSpecialApplyVO();
            BeanUtils.copyProperties(orderItemDO, vo);


            vo.setOrgFreight(orderItemDO.getOneSeaFreight());
            vo.setSubtotalFreight(orderItemDO.getSeaFreight());
            vo.setFreightCurrency(Long.valueOf(orderItemDO.getSeaFreightCurrency()));
            vo.setFreightVolume(orderItemDO.getSeaFreightVolume());

            if (vo.getCharging() == 0) {
                vo.setClearanceFreight(null); // 因字段冲突，copy后需要将该字段置空
                vo.setOrgClearanceFreight(orderItemDO.getOneClearanceFreight());
                vo.setSubtotalClearanceFreight(orderItemDO.getClearanceFreight());
                vo.setClearanceFreightCurrency(Long.valueOf(orderItemDO.getClearanceFreightCurrency()));
                vo.setClearanceFreightVolume(orderItemDO.getClearanceFreightVolume());
            }
            if (type == 3) {
                vo.setOrgCommissionType(orderItemDO.getCommissionType());
                vo.setOrgShadeCommissionAmount(orderItemDO.getHiddenCommission());
                vo.setShadeCommissionAmount(orderItemDO.getHiddenCommission());
                vo.setOrgLightCommissionAmount(orderItemDO.getPlainCommission());
                vo.setLightCommissionAmount(orderItemDO.getPlainCommission());
            }
        } else {
            // 重泡货设置针对订单
            OrderDO orderDO = orderMapper.selectById(orderId);
            if (Objects.isNull(orderDO)) {
                throw exception(ORDER_NOT_EXISTS);
            }
            vo = new OrderSpecialApplyVO();
            ZhongPaoBestVO zhongPaoBestVO = new ZhongPaoBestVO();
            OrderApprovalTypeEnum typeEnum = OrderApprovalTypeEnum.valueOf(type);
            BeanUtils.copyProperties(orderDO, vo);
            if (type == 4 || type == 5) {
                LogisticsInfoDto logisticsInfoDto = warehouseLineMapper.getStartInfoAndDestInfoByLineId(orderDO.getLineId());
                if (Objects.isNull(logisticsInfoDto)) {
                    throw exception(TRANSPORT_LINE_NOT_EXISTS);
                }
                OrderConsignorDO consignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, orderId).orderByDesc(OrderConsignorDO::getId).last("limit 1"));
                OrderConsigneeDO consigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, orderId).orderByDesc(OrderConsigneeDO::getId).last("limit 1"));
                CustomerZhongPaoQueryVO customerZhongPaoQueryVO = new CustomerZhongPaoQueryVO();
                if (Objects.nonNull(consignorDO)) {
                    customerZhongPaoQueryVO.setConsignorId(consignorDO.getCustomerId());
                }
                if (Objects.nonNull(consigneeDO)) {
                    customerZhongPaoQueryVO.setConsigneeId(consigneeDO.getCustomerId());
                }
                customerZhongPaoQueryVO.setDepartureId(logisticsInfoDto.getStartCityId());
                customerZhongPaoQueryVO.setObjectiveId(logisticsInfoDto.getDestCityId());

                customerZhongPaoQueryVO.setStartWarehouseId(logisticsInfoDto.getStartWarehouseId());
                customerZhongPaoQueryVO.setDestWarehouseId(logisticsInfoDto.getDestWarehouseId());

                zhongPaoBestVO = zhongPaoService.getCustomerBestZhongPao(customerZhongPaoQueryVO);
                if (Objects.isNull(zhongPaoBestVO)) {
                    zhongPaoBestVO = new ZhongPaoBestVO();
                }
            }
            switch (typeEnum) {
                case WEIGHT_DISCOUNT:
                    vo.setWVolume(null);
                    vo.setOrgWVolume(Objects.nonNull(orderDO.getWeightUnit()) ? orderDO.getWeightUnit() : zhongPaoBestVO.getZhongEdge());
                    break;
                case BUBBLE_DISCOUNT:
                    vo.setVWeight(null);
                    vo.setOrgVWeight(Objects.nonNull(orderDO.getVolumeUnit()) ? orderDO.getVolumeUnit() : zhongPaoBestVO.getPaoEdge());
                    break;
                case BUBBLE_WEIGHT_SPECIAL_DISCOUNT:
                    vo.setVWeight(null);
                    vo.setOrgVWeight(orderDO.getVWeight());
                    break;
            }
        }
        vo.setOrderApprovalHeadBaseVO(baseVO);
        return vo;
    }


    @Override
    public OrderSpecialBatchApplyVO approvalOrderSpecialByOrderId(Long orderId, Integer type, boolean isResubmit) {
        OrderSpecialBatchApplyVO orderSpecialBatchApplyVO = new OrderSpecialBatchApplyVO();


        OrderApprovalDO orderApprovalDO = orderApprovalMapper.newItemInfo(null, orderId, type);
        OrderApprovalHeadBaseVO baseVO = this.getOrderApprovalHeadInfo(orderId);
        isResubmit = Objects.isNull(orderApprovalDO) || 1 != orderApprovalDO.getStatus();

        if (Objects.nonNull(orderApprovalDO) && !isResubmit) {
            orderSpecialBatchApplyVO = JSONObject.parseObject(orderApprovalDO.getDetails(), OrderSpecialBatchApplyVO.class);
            orderSpecialBatchApplyVO.setOrderApprovalHeadBaseVO(baseVO);
            orderSpecialBatchApplyVO.setFormId(orderApprovalDO.getFormId());
            orderSpecialBatchApplyVO.setOrderApprovalId(orderApprovalDO.getOrderApprovalId());
            return orderSpecialBatchApplyVO;
        }

        orderSpecialBatchApplyVO.setOrderApprovalHeadBaseVO(baseVO);

        if (Objects.equals(type, OrderApprovalTypeEnum.DISCOUNT_APPLY_BATCH.getValue()) || Objects.equals(type, OrderApprovalTypeEnum.ADMIN_DISCOUNT_BATCH.getValue())) {

            List<OrderItemDO> itemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderId).orderByDesc(OrderItemDO::getOrderItemId));
            if (CollectionUtil.isEmpty(itemDOList)) {
                throw exception(ORDER_ITEM_PROD_NOT_EXISTS);
            }

            List<OrderSpecialBatchApplyOrderItemDetailVO> orderSpecialBatchApplyOrderItemDetailVOList = itemDOList.stream().map(orderItemDO -> {
                OrderSpecialBatchApplyOrderItemDetailVO vo = new OrderSpecialBatchApplyOrderItemDetailVO();
                BeanUtils.copyProperties(orderItemDO, vo);

                vo.setOrgFreight(orderItemDO.getOneSeaFreight());
                vo.setSubtotalFreight(orderItemDO.getSeaFreight());
                vo.setFreightCurrency(Long.valueOf(orderItemDO.getSeaFreightCurrency()));
                vo.setFreightVolume(orderItemDO.getSeaFreightVolume());

                if (vo.getCharging() == 0) {
                    vo.setClearanceFreight(null); // 因字段冲突，copy后需要将该字段置空
                    vo.setOrgClearanceFreight(orderItemDO.getOneClearanceFreight());
                    vo.setSubtotalClearanceFreight(orderItemDO.getClearanceFreight());
                    vo.setClearanceFreightCurrency(Long.valueOf(orderItemDO.getClearanceFreightCurrency()));
                    vo.setClearanceFreightVolume(orderItemDO.getClearanceFreightVolume());
                }
                if (type == 3) {
                    vo.setOrgCommissionType(orderItemDO.getCommissionType());
                    vo.setOrgShadeCommissionAmount(orderItemDO.getHiddenCommission());
                    vo.setShadeCommissionAmount(orderItemDO.getHiddenCommission());
                    vo.setOrgLightCommissionAmount(orderItemDO.getPlainCommission());
                    vo.setLightCommissionAmount(orderItemDO.getPlainCommission());
                }

                return vo;
            }).collect(Collectors.toList());

            orderSpecialBatchApplyVO.setBatchApplyOrderItemDetailVOList(orderSpecialBatchApplyOrderItemDetailVOList);
        }

        return orderSpecialBatchApplyVO;
    }

    @Override
    public OrderBackVO getOrder(Long orderId) {
        OrderDO orderDO = orderMapper.selectById(orderId);
        if (Objects.isNull(orderDO)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        OrderBackVO backVO = OrderConvert.INSTANCE.convert(orderDO);
        if (StringUtils.isNotBlank(backVO.getExternalWarehouseJson())) {
            backVO.setExternalWarehouseDtoList(JSONObject.parseArray(backVO.getExternalWarehouseJson(), ExternalWarehouseDto.class));
        }
        // 发货人信息
        OrderConsignorDO orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsignorDO::getId).last("limit 1"));
//        if (Objects.isNull(orderConsignorDO)) {
//            throw exception(ORDER_CONSIGNOR_NOT_EXISTS);
//        }
        if (Objects.nonNull(orderConsignorDO)) {
            backVO.setConsignorVO(OrderConsignorConvert.INSTANCE.convert(orderConsignorDO));
            backVO.setConsignorId(orderConsignorDO.getCustomerId());
            backVO.setConsignorContactsId(orderConsignorDO.getCustomerContactsId());
        }
        // 收货人信息
        OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsigneeDO::getId).last("limit 1"));
//        if (Objects.isNull(orderConsigneeDO)) {
//            throw exception(ORDER_CONSIGNEE_NOT_EXISTS);
//        }
        if (Objects.nonNull(orderConsigneeDO)) {
            backVO.setConsigneeVO(OrderConsigneeConvert.INSTANCE.convert(orderConsigneeDO));
            backVO.setConsigneeId(orderConsigneeDO.getCustomerId());
            backVO.setConsigneeContactsId(orderConsigneeDO.getCustomerContactsId());
            backVO.setConsigneeAddress(orderConsigneeDO.getAddress());
            backVO.setHarvestMethod(orderConsigneeDO.getHarvestMethod());
            backVO.setCity(orderConsigneeDO.getCity());
            backVO.setProvince(orderConsigneeDO.getProvince());
            backVO.setCountry(orderConsigneeDO.getCountry());
        }

        // 始发地
        OrderDepartureDO orderDepartureDO = orderDepartureService.getOne(new LambdaQueryWrapper<OrderDepartureDO>().eq(OrderDepartureDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderDepartureDO::getId).last("limit 1"));
        backVO.setOrderDepartureVO(OrderDepartureConvert.INSTANCE.convert(orderDepartureDO));
        backVO.setDepartureId(orderDepartureDO.getDepartureId());

        // 目的地
        OrderObjectiveDO orderObjectiveDO = orderObjectiveService.getOne(new LambdaQueryWrapper<OrderObjectiveDO>().eq(OrderObjectiveDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderObjectiveDO::getId).last("limit 1"));
        backVO.setOrderObjectiveVO(OrderObjectiveConvert.INSTANCE.convert(orderObjectiveDO));
        backVO.setObjectiveId(orderObjectiveDO.getObjectiveId());

        // 商品信息
        List<OrderItemDO> itemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderItemDO::getOrderItemId));
        if (CollectionUtil.isNotEmpty(itemDOList)) {
            backVO.setOrderItemVOList(OrderItemConvert.INSTANCE.convertList(itemDOList));
        }
        // 物流信息查询
        LogisticsInfoDto logisticsInfoDto = warehouseLineMapper.getStartInfoAndDestInfoByLineId(backVO.getLineId());
        if (Objects.isNull(logisticsInfoDto)) {
            throw exception(NOT_FIND_LOGISTICS_INFO);
        }
        logisticsInfoDto.setLineId(backVO.getLineId());
        logisticsInfoDto.setTransportId(backVO.getTransportId());
        logisticsInfoDto.setChannelId(backVO.getChannelId());
        backVO.setLogisticsInfoDto(logisticsInfoDto);
//        if (backVO.getOrderNo().startsWith("DRAFT")) {
//            backVO.setOrderNo("");
//        }
        return backVO;
    }

    @Override
    public OrderBackVO getOrderByNo(String orderNo) {
        OrderDO orderDO = orderMapper.selectOne(new LambdaQueryWrapper<OrderDO>().eq(OrderDO::getOrderNo, orderNo).last("limit 1"));
        if (Objects.isNull(orderDO)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        OrderBackVO backVO = OrderConvert.INSTANCE.convert(orderDO);
        if (StringUtils.isNotBlank(backVO.getExternalWarehouseJson())) {
            backVO.setExternalWarehouseDtoList(JSONObject.parseArray(backVO.getExternalWarehouseJson(), ExternalWarehouseDto.class));
        }
        // 发货人信息
        OrderConsignorDO orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsignorDO::getId).last("limit 1"));
//        if (Objects.isNull(orderConsignorDO)) {
//            throw exception(ORDER_CONSIGNOR_NOT_EXISTS);
//        }
        if (Objects.nonNull(orderConsignorDO)) {
            backVO.setConsignorVO(OrderConsignorConvert.INSTANCE.convert(orderConsignorDO));
            backVO.setConsignorId(orderConsignorDO.getCustomerId());
            backVO.setConsignorContactsId(orderConsignorDO.getCustomerContactsId());
        }
        // 收货人信息
        OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsigneeDO::getId).last("limit 1"));
//        if (Objects.isNull(orderConsigneeDO)) {
//            throw exception(ORDER_CONSIGNEE_NOT_EXISTS);
//        }
        if (Objects.nonNull(orderConsigneeDO)) {
            backVO.setConsigneeVO(OrderConsigneeConvert.INSTANCE.convert(orderConsigneeDO));
            backVO.setConsigneeId(orderConsigneeDO.getCustomerId());
            backVO.setConsigneeContactsId(orderConsigneeDO.getCustomerContactsId());
            backVO.setConsigneeAddress(orderConsigneeDO.getAddress());
            backVO.setHarvestMethod(orderConsigneeDO.getHarvestMethod());
            backVO.setCity(orderConsigneeDO.getCity());
            backVO.setProvince(orderConsigneeDO.getProvince());
            backVO.setCountry(orderConsigneeDO.getCountry());
        }

        // 始发地
        OrderDepartureDO orderDepartureDO = orderDepartureService.getOne(new LambdaQueryWrapper<OrderDepartureDO>().eq(OrderDepartureDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderDepartureDO::getId).last("limit 1"));
        backVO.setOrderDepartureVO(OrderDepartureConvert.INSTANCE.convert(orderDepartureDO));
        backVO.setDepartureId(orderDepartureDO.getDepartureId());

        // 目的地
        OrderObjectiveDO orderObjectiveDO = orderObjectiveService.getOne(new LambdaQueryWrapper<OrderObjectiveDO>().eq(OrderObjectiveDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderObjectiveDO::getId).last("limit 1"));
        backVO.setOrderObjectiveVO(OrderObjectiveConvert.INSTANCE.convert(orderObjectiveDO));
        backVO.setObjectiveId(orderObjectiveDO.getObjectiveId());

        // 商品信息
        List<OrderItemDO> itemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderItemDO::getOrderItemId));
        if (CollectionUtil.isNotEmpty(itemDOList)) {
            backVO.setOrderItemVOList(OrderItemConvert.INSTANCE.convertList(itemDOList));
        }
        // 物流信息查询
        LogisticsInfoDto logisticsInfoDto = warehouseLineMapper.getStartInfoAndDestInfoByLineId(backVO.getLineId());
        if (Objects.isNull(logisticsInfoDto)) {
            throw exception(NOT_FIND_LOGISTICS_INFO);
        }
        logisticsInfoDto.setLineId(backVO.getLineId());
        logisticsInfoDto.setTransportId(backVO.getTransportId());
        logisticsInfoDto.setChannelId(backVO.getChannelId());
        backVO.setLogisticsInfoDto(logisticsInfoDto);
//        if (backVO.getOrderNo().startsWith("DRAFT")) {
//            backVO.setOrderNo("");
//        }
        return backVO;
    }

    @Override
    public OrderBackVO getParentOrder(Long orderId) {
        // TODO 后面可以在订单列表返回初始母订单id，前端可以直接通过初始母订单id查询订单详情
        OrderDO parentOrder = orderMapper.selectById(orderId);
        if (Objects.isNull(parentOrder)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        // 判断是否为母订单，不是则重新获取，此处只获得原始母订单，子订单拆单后的子订单也是获取原始母订单
        if (Objects.nonNull(parentOrder.getParentOrderId()) && parentOrder.getParentOrderId() > 0L) {
            if (Objects.nonNull(parentOrder.getInitialParentOrderId()) && parentOrder.getInitialParentOrderId() > 0L) {
                parentOrder = orderMapper.selectById(parentOrder.getInitialParentOrderId());
            } else {
                String[] numberStr = parentOrder.getOrderNo().split(StrUtil.DASHED);
                parentOrder = orderMapper.selectOne(new LambdaQueryWrapper<OrderDO>().eq(OrderDO::getOrderNo, numberStr[0]).last("limit 1"));
                if (Objects.isNull(parentOrder)) {
                    throw exception(PARENT_ORDER_NOT_EXISTS);
                }
            }
        }
        OrderBackVO backVO = OrderConvert.INSTANCE.convert(parentOrder);
        // 发货人信息
        OrderConsignorDO orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, parentOrder.getOrderId()).orderByDesc(OrderConsignorDO::getId).last("limit 1"));
//        if (Objects.isNull(orderConsignorDO)) {
//            throw exception(ORDER_CONSIGNOR_NOT_EXISTS);
//        }
        if (Objects.nonNull(orderConsignorDO)) {
            backVO.setConsignorVO(OrderConsignorConvert.INSTANCE.convert(orderConsignorDO));
            backVO.setConsignorId(orderConsignorDO.getCustomerId());
            backVO.setConsignorContactsId(orderConsignorDO.getCustomerContactsId());
        }
        // 收货人信息
        OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, parentOrder.getOrderId()).orderByDesc(OrderConsigneeDO::getId).last("limit 1"));
//        if (Objects.isNull(orderConsigneeDO)) {
//            throw exception(ORDER_CONSIGNEE_NOT_EXISTS);
//        }
        if (Objects.nonNull(orderConsigneeDO)) {
            backVO.setConsigneeVO(OrderConsigneeConvert.INSTANCE.convert(orderConsigneeDO));
            backVO.setConsigneeId(orderConsigneeDO.getCustomerId());
            backVO.setConsigneeContactsId(orderConsigneeDO.getCustomerContactsId());
            backVO.setConsigneeAddress(orderConsigneeDO.getAddress());
            backVO.setHarvestMethod(orderConsigneeDO.getHarvestMethod());
            backVO.setCity(orderConsigneeDO.getCity());
            backVO.setProvince(orderConsigneeDO.getProvince());
            backVO.setCountry(orderConsigneeDO.getCountry());
        }

        // 始发地
        OrderDepartureDO orderDepartureDO = orderDepartureService.getOne(new LambdaQueryWrapper<OrderDepartureDO>().eq(OrderDepartureDO::getOrderId, parentOrder.getOrderId()).orderByDesc(OrderDepartureDO::getId).last("limit 1"));
        backVO.setOrderDepartureVO(OrderDepartureConvert.INSTANCE.convert(orderDepartureDO));
        backVO.setDepartureId(orderDepartureDO.getDepartureId());

        // 目的地
        OrderObjectiveDO orderObjectiveDO = orderObjectiveService.getOne(new LambdaQueryWrapper<OrderObjectiveDO>().eq(OrderObjectiveDO::getOrderId, parentOrder.getOrderId()).orderByDesc(OrderObjectiveDO::getId).last("limit 1"));
        backVO.setOrderObjectiveVO(OrderObjectiveConvert.INSTANCE.convert(orderObjectiveDO));
        backVO.setObjectiveId(orderObjectiveDO.getObjectiveId());

        // 商品信息
        List<OrderItemDO> itemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, parentOrder.getOrderId()).orderByDesc(OrderItemDO::getOrderItemId));
        if (CollectionUtil.isNotEmpty(itemDOList)) {
            backVO.setOrderItemVOList(OrderItemConvert.INSTANCE.convertList(itemDOList));
        }
        // 物流信息查询
        LogisticsInfoDto logisticsInfoDto = warehouseLineMapper.getStartInfoAndDestInfoByLineId(backVO.getLineId());
        if (Objects.isNull(logisticsInfoDto)) {
            throw exception(NOT_FIND_LOGISTICS_INFO);
        }
        logisticsInfoDto.setLineId(backVO.getLineId());
        logisticsInfoDto.setTransportId(backVO.getTransportId());
        logisticsInfoDto.setChannelId(backVO.getChannelId());
        backVO.setLogisticsInfoDto(logisticsInfoDto);
//        if (backVO.getOrderNo().startsWith("DRAFT")) {
//            backVO.setOrderNo("");
//        }
        return backVO;
    }

    @Override
    public OrderBackInfoDto info(Long orderId) {
        OrderBackInfoDto dto = orderMapper.info(orderId, I18nMessage.getLang());
        if (Objects.isNull(dto)) {
            throw exception(ORDER_NOT_EXISTS);
        }

        if (dto.getSumVolume().compareTo(BigDecimal.ZERO) == 0) {
            dto.setWVolume(BigDecimal.ZERO);
        }
        if (dto.getSumWeight().compareTo(BigDecimal.ZERO) == 0) {
            dto.setVWeight(BigDecimal.ZERO);
        }

        // 判断请求端口
        LoginUser user = SecurityFrameworkUtils.getLoginUser();
        if (Objects.nonNull(user)) {
            dto.setUserType(user.getUserType());
        } else {
            dto.setUserType(UserTypeEnum.MEMBER.getValue());
        }

        // 物流信息查询
        LogisticsInfoDto initialLogisticsInfoDto =
                warehouseLineMapper.getStartInfoAndDestInfoByLineId(dto.getLineId());
        if (Objects.isNull(initialLogisticsInfoDto)) {
            throw exception(NOT_FIND_LOGISTICS_INFO);
        }
        initialLogisticsInfoDto.setLineId(dto.getLineId());
        initialLogisticsInfoDto.setTransportId(dto.getTransportId());
        initialLogisticsInfoDto.setChannelId(dto.getChannelId());
        //保存初始物流信息，该信息为收费信息
        dto.setInitialLogisticsInfoDto(initialLogisticsInfoDto);
        LogisticsInfoDto logisticsInfoDto = new LogisticsInfoDto();
        BeanUtils.copyProperties(initialLogisticsInfoDto, logisticsInfoDto);
        if (Objects.nonNull(dto.getAdjustToDestWarehouseId()) &&
                dto.getAdjustToDestWarehouseId() > 0L) {

            // 如果有始发仓调仓记录id，则获取最新的调仓仓库信息
            WarehouseRegionVO startWarehouseRegionVO =
                    warehouseMapper.findWarehouseRegion(dto.getAdjustToDestWarehouseId());
            if (Objects.nonNull(startWarehouseRegionVO)) {
                logisticsInfoDto.setStartWarehouseId(dto.getAdjustToDestWarehouseId());
                logisticsInfoDto.setStartCityId(startWarehouseRegionVO.getShi());
                logisticsInfoDto.setStartHead(startWarehouseRegionVO.getHead());
                logisticsInfoDto.setStartTell(startWarehouseRegionVO.getTell());
                logisticsInfoDto.setStartTitleZh(startWarehouseRegionVO.getTitleZh());
                logisticsInfoDto.setStartTitleEn(startWarehouseRegionVO.getTitleEn());
                logisticsInfoDto.setStartAddressZh(startWarehouseRegionVO.getAddressZh());
                logisticsInfoDto.setStartAddressEn(startWarehouseRegionVO.getAddressEn());
                logisticsInfoDto.setStartVolume(startWarehouseRegionVO.getVolume());
            }
        }
        if (Objects.nonNull(dto.getDestAdjustToDestWarehouseId()) &&
                dto.getDestAdjustToDestWarehouseId() > 0L) {
            // 如果有目的地的目的仓调仓记录id，则获取最新的调仓仓库信息
            WarehouseRegionVO destWarehouseRegionVO =
                    warehouseMapper.findWarehouseRegion(dto.getDestAdjustToDestWarehouseId());
            if (Objects.nonNull(destWarehouseRegionVO)) {
                logisticsInfoDto.setDestWarehouseId(dto.getDestAdjustToDestWarehouseId());
                logisticsInfoDto.setDestCityId(destWarehouseRegionVO.getShi());
                logisticsInfoDto.setDestHead(destWarehouseRegionVO.getHead());
                logisticsInfoDto.setDestTell(destWarehouseRegionVO.getTell());
                logisticsInfoDto.setDestTitleZh(destWarehouseRegionVO.getTitleZh());
                logisticsInfoDto.setDestTitleEn(destWarehouseRegionVO.getTitleEn());
                logisticsInfoDto.setDestAddressZh(destWarehouseRegionVO.getAddressZh());
                logisticsInfoDto.setDestAddressEn(destWarehouseRegionVO.getAddressEn());
                logisticsInfoDto.setDestVolume(destWarehouseRegionVO.getVolume());
            }
        }
        // 保存可能是调仓后的物流信息，该信息为当前货物正在经理的物流信息线路
        dto.setLogisticsInfoDto(logisticsInfoDto);
        // 始发地信息
        OrderDepartureDO orderDepartureDO =
                orderDepartureService.getOne(
                        new LambdaQueryWrapper<OrderDepartureDO>().
                                eq(OrderDepartureDO::getOrderId, orderId).
                                orderByDesc(OrderDepartureDO::getId).last("limit 1"));
        if (Objects.nonNull(orderDepartureDO)) {
            dto.setDepartureVO(OrderDepartureConvert.INSTANCE.convert(orderDepartureDO));
        }
        // 目的地信息
        OrderObjectiveDO orderObjectiveDO =
                orderObjectiveService.getOne(new LambdaQueryWrapper<OrderObjectiveDO>().eq(OrderObjectiveDO::getOrderId, orderId).orderByDesc(OrderObjectiveDO::getId).last("limit 1"));
        if (Objects.nonNull(orderObjectiveDO)) {
            dto.setObjectiveVO(OrderObjectiveConvert.INSTANCE.convert(orderObjectiveDO));
        }
        // 发货人信息
        OrderConsignorDO orderConsignorDO =
                orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, orderId).orderByDesc(OrderConsignorDO::getId).last("limit 1"));
        if (Objects.nonNull(orderConsignorDO)) {
            dto.setConsignorVO(OrderConsignorConvert.INSTANCE.convert(orderConsignorDO));
        }
        // 收货人信息
        OrderConsigneeDO orderConsigneeDO =
                orderConsigneeService.getOne(
                        new LambdaQueryWrapper<OrderConsigneeDO>().eq(
                                        OrderConsigneeDO::getOrderId, orderId).
                                orderByDesc(OrderConsigneeDO::getId).last("limit 1"));

        if (Objects.nonNull(orderConsigneeDO)) {

            OrderConsigneeBackVO v1 =
                    OrderConsigneeConvert.INSTANCE.convert(orderConsigneeDO);

            /*
            LambdaQueryWrapper q1 = new LambdaQueryWrapper<CustomerContactsDO>().eq(
                            CustomerContactsDO::getCustomerId,
                            orderConsigneeDO.getCustomerId()).
                    eq(CustomerContactsDO::getIsDefault, 1);
            List<CustomerContactsDO> list =
                    customerContactsService.selectList(q1);
            if (CollectionUtil.isNotEmpty(list)) {

            }*/

            dto.setConsigneeVO(v1);
            dto.setConsigneeAddress(orderConsigneeDO.getAddress());
            dto.setHarvestMethod(orderConsigneeDO.getHarvestMethod());
            dto.setCity(orderConsigneeDO.getCity());
            dto.setProvince(orderConsigneeDO.getProvince());
            dto.setCountry(orderConsigneeDO.getCountry());
        }
        // 商品列表信息
        //oneSeaFreight 运费单价
        //oneClearanceFreight 清关费单价
        List<OrderItemBackVO> backVOList =
                orderItemMapper.infoItemList(orderId, I18nMessage.getLang());
        if (CollectionUtil.isNotEmpty(backVOList)) {
            backVOList = fillOrderItemProperties(backVOList);
            // 转换数据字段
            dto.setWVolume(backVOList.stream().filter(item -> Objects.nonNull(item.getWarehouseInInfoVO()) && item.getWarehouseInInfoVO().getCartonsNum() > 0).map(OrderItemBackVO::getWVolume).map(BigDecimal::new).reduce(BigDecimal.ZERO, BigDecimal::add));
            dto.setVWeight(backVOList.stream().filter(item -> Objects.nonNull(item.getWarehouseInInfoVO()) && item.getWarehouseInInfoVO().getCartonsNum() > 0).map(OrderItemBackVO::getVWeight).map(BigDecimal::new).reduce(BigDecimal.ZERO, BigDecimal::add));
            dto.setSumQuantity(backVOList.stream().filter(item -> Objects.nonNull(item.getWarehouseInInfoVO()) && item.getWarehouseInInfoVO().getCartonsNum() > 0).map(OrderItemBackVO::getQQuantity).map(BigDecimal::new).reduce(BigDecimal.ZERO, BigDecimal::add).intValue());

            dto.setOrderItemVOList(backVOList);
        }
        // 订单动态
        // 订单的到仓时间 去动态值 businessTime
        List<OrderTimeDO> orderTimeList =
                orderTimeMapper.selectList(
                        new LambdaQueryWrapper<OrderTimeDO>().eq(OrderTimeDO::getOrderId, orderId).orderByAsc(OrderTimeDO::getId));
        if (CollectionUtil.isNotEmpty(orderTimeList)) {
//            getDaoCanTiam(orderTimeList);
            dto.setOrderTimeVOList(OrderTimeConvert.INSTANCE.convertList(
                    orderTimeList));
        }
        if (Objects.equals(TransportTypeShortEnum.SEA_CONTAINER.getValue(), dto.getTransportId())
                || Objects.equals(TransportTypeShortEnum.MARINE_CONTAINER.getValue(), dto.getTransportId())) {
            dto.setChannelId(null);
        }
        if (dto.getOrderNo().startsWith("DRAFT")) {
            dto.setOrderNo("");
        }
        // 查询创建人昵称信息
        // 先判断订单是客户端创建还是管理端创建，订单有userId且大于0的为客户端创建，否则管理端创建
        if (Objects.isNull(dto.getUserId()) || 0L == dto.getUserId()) {
            // 管理端用户
            AdminUserRespDTO adminUserRespDTO = adminUserApi.getUser(Long.valueOf(StringUtils.isBlank(dto.getCreator()) ? "0" : dto.getCreator()));
            if (Objects.nonNull(adminUserRespDTO)) {
                dto.setCreatorName(adminUserRespDTO.getNickname());
            }
            dto.setUserType(2);
        } else {
            UserRespDTO userRespDTO = memberUserApi.getUser(dto.getUserId());
            if (Objects.nonNull(userRespDTO)) {
                dto.setCreatorName(userRespDTO.getNickname());
            }
            dto.setUserType(1);
        }
        return dto;
    }

    /*
      添加的函数
     */
    private void getDaoCanTiam(List<OrderTimeDO> orderTimeList) {
        if (CollectionUtil.isEmpty(orderTimeList)) {
            return;
        }

        for (OrderTimeDO i : orderTimeList
        ) {
            if (i.getTitleZh() != null && i.getTitleZh().equals("到仓")) {
                //i.getBusinessTime();
                long l = i.getOrderId();
                //long shpId = orderTimeMapper.getShipment_id(l);
                //在订单操作日志中获取卸柜时间
                Date d = orderTimeMapper.getUlboxtime(l);
                if (d != null) i.setBusinessTime(d);
            }
        }
    }

    @NotNull
    private List<OrderItemBackVO> fillOrderItemProperties(
            List<OrderItemBackVO> backVOList) {
        if (CollectionUtil.isEmpty(backVOList)) {
            return backVOList;
        }
        return backVOList.stream().peek(item -> {

            if (!item.getChannelManualPricing() &&
                    !item.getSpecialPriceType() &&
                    !item.getSplitCustomPriceType() &&
                    Objects.nonNull(item.getOriginalSeaFreight())
                    && item.getOriginalSeaFreight().compareTo(BigDecimal.ZERO) == 0) {
                // 表示当前运费没有原价，且不是设置了相关特价，则将预付状态置null
                item.setIsPayAdvance(null);
            }
            // 运费成本价=销售价-明佣-暗佣
            item.setCostSeaFreight(item.getOneSeaFreight().
                    subtract(item.getPlainCommission()).
                    subtract(item.getHiddenCommission()));
            // 清关费成本价=销售价
            item.setCostClearanceFreight(item.getOneClearanceFreight());
            if (Objects.nonNull(item.getWarehouseInInfoVO())) {
                WarehouseInInfoVO warehouseInInfoVO = item.getWarehouseInInfoVO();
                warehouseInInfoVO.setQuantityAll(Objects.nonNull(warehouseInInfoVO.getQuantityAll()) && new BigDecimal(warehouseInInfoVO.getQuantityAll()).compareTo(item.getMinMeteringQuantity()) > 0 ? warehouseInInfoVO.getQuantityAll() : item.getMinMeteringQuantity().intValue());
                item.setWarehouseInInfoVO(warehouseInInfoVO);
                if (warehouseInInfoVO.getCartonsNum() > 0) {
                    item.setWVolume(Objects.nonNull(item.getChargeVolume()) && item.getChargeVolume().compareTo(item.getMinMeteringVolume()) > 0 ? item.getChargeVolume().toString() : item.getMinMeteringVolume().toString());
                    item.setVWeight(Objects.nonNull(item.getChargeWeight()) && item.getChargeWeight().compareTo(item.getMinMeteringWeight()) > 0 ? item.getChargeWeight().toString() : item.getMinMeteringWeight().toString());
                    item.setQQuantity(Objects.nonNull(item.getChargeQuantity()) && item.getChargeQuantity().compareTo(item.getMinMeteringQuantity()) > 0 ? item.getChargeQuantity().toString() : item.getMinMeteringQuantity().toString());
                } else {
                    item.setWVolume(BigDecimal.ZERO.toString());
                    item.setVWeight(BigDecimal.ZERO.toString());
                    item.setQQuantity(BigDecimal.ZERO.toString());
                }
            } else {
                item.setWVolume(BigDecimal.ZERO.toString());
                item.setVWeight(BigDecimal.ZERO.toString());
                item.setQQuantity(BigDecimal.ZERO.toString());
            }
            //入仓类型，多个用逗号分隔
            OrderItemBackVO warehouseInDO = orderWarehouseInMapper.getWarehouseInByItemIdAndOrderId(item.getOrderId(), item.getOrderItemId(), I18nMessage.getLang());
            if (Objects.nonNull(warehouseInDO) && StringUtils.isNotBlank(warehouseInDO.getWarehouseType())) {
                item.setWarehouseType(warehouseInDO.getWarehouseType());
            }
            //入仓包装单位，多个用逗号分隔
            if (Objects.nonNull(warehouseInDO) && StringUtils.isNotBlank(warehouseInDO.getSpecificationType())) {
                item.setSpecificationType(warehouseInDO.getSpecificationType());
            }
            if (Objects.nonNull(warehouseInDO) && StringUtils.isNotBlank(warehouseInDO.getWarehouseRecordRemark())) {
                item.setWarehouseRecordRemark(warehouseInDO.getWarehouseRecordRemark());
            }

            // 转换赋值初始数值
            item.setInitialChargeWeight(item.getChargeWeight());
            item.setInitialChargeVolume(item.getChargeVolume());
            item.setInitialChargeQuantity(item.getChargeQuantity());
            // 订单详情品名输出的收费值改为对比最小值后的收费值
            item.setChargeWeight(new BigDecimal(item.getVWeight()));
            item.setChargeVolume(new BigDecimal(item.getWVolume()));
            item.setChargeQuantity(new BigDecimal(item.getQQuantity()));
            // 订单项到仓异常登记信息
            if (Objects.nonNull(item.getWarehouseCheckInfoVO())) {
                List<String> exceptionKeys = Arrays.asList(OrderExceptionEnum.ORDER_MISS_EXCEPTION.getKey(),
                        OrderExceptionEnum.ORDER_SUPERFLUOUS_GOODS_EXCEPTION.getKey(),
                        OrderExceptionEnum.ORDER_DAMAGE_EXCEPTION.getKey(),
                        OrderExceptionEnum.ORDER_IN_WATER_EXCEPTION.getKey(),
                        OrderExceptionEnum.ORDER_ABNORMAL_WEIGHT_EXCEPTION.getKey());
                List<OrderExceptionDO> orderExceptionDOList = orderExceptionService.list(new LambdaQueryWrapper<OrderExceptionDO>()
                        .eq(OrderExceptionDO::getOrderItemId, item.getOrderItemId())
                        .in(OrderExceptionDO::getOrderExceptionType, exceptionKeys));
                if (CollectionUtil.isNotEmpty(orderExceptionDOList)) {
                    List<ExceptionTypeResultVO> itemExceptionList = new ArrayList<>();
                    for (OrderExceptionDO orderExceptionDO : orderExceptionDOList) {
                        OrderExceptionEnum exceptionEnum = OrderExceptionEnum.getEnumByKey(orderExceptionDO.getOrderExceptionType());
                        // 异常状态0:待处理，1处理中，2已处理
                        String result = orderExceptionDO.getOrderExceptionStatus() == 0 ? "待处理" : (orderExceptionDO.getOrderExceptionStatus() == 1 ? "1处理中" : "已处理");
                        ExceptionTypeResultVO typeResultVO = new ExceptionTypeResultVO();
                        typeResultVO.setExceptionType(I18nMessage.getLang() == 0 ? exceptionEnum.getZhValueDesc() : exceptionEnum.getEnValueDesc());
                        typeResultVO.setResult(result);
                        itemExceptionList.add(typeResultVO);
                    }
                    item.setItemExceptionList(itemExceptionList);
                }
            }
            //订单项入仓影像
            List<OrderWarehousePictureDO> warehousePictureList =
                    orderWarehousePictureService.getWarehousePictureList(5, item.getOrderItemId());
            if (CollectionUtil.isNotEmpty(warehousePictureList)) {
                List<String> pictureUrls = warehousePictureList.stream().map(OrderWarehousePictureDO::getUrl).collect(Collectors.toList());
                item.setPictureUrls(pictureUrls);
            }
            //订单项到仓影像
            List<OrderWarehousePictureDO> warehouseCheckPictureList =
                    orderWarehousePictureService.getWarehousePictureList(7, item.getOrderItemId());
            if (CollectionUtil.isNotEmpty(warehouseCheckPictureList)) {
                List<String> checkPictureUrls = warehouseCheckPictureList.stream().map(OrderWarehousePictureDO::getUrl).collect(Collectors.toList());
                item.setCheckPictureUrls(checkPictureUrls);
            }
            if ((Objects.nonNull(item.getChannelManualPricing()) && item.getChannelManualPricing())
                    || (Objects.nonNull(item.getSpecialPriceType()) && item.getSpecialPriceType())
                    || (Objects.nonNull(item.getSplitCustomPriceType()) && item.getSplitCustomPriceType())) {
                if (item.getOriginalSeaFreight().compareTo(BigDecimal.ZERO) == 0) {
                    item.setOriginalSeaFreight(item.getOneSeaFreight()
                            .subtract(item.getBrandFreightPrice())
                            .subtract(item.getElectrifiedFreightPrice())
                            .subtract(item.getLiquidFreightPrice())
                            .add(item.getDiscountFreightPrice()));
                    item.setAfterDiscountSeaFreight(item.getOriginalSeaFreight()
                            .add(item.getBrandFreightPrice())
                            .add(item.getElectrifiedFreightPrice())
                            .add(item.getLiquidFreightPrice())
                            .add(item.getPlainCommission())
                            .subtract(item.getDiscountFreightPrice()));
                }
                if (item.getOriginalClearanceFreight().compareTo(BigDecimal.ZERO) == 0) {
                    item.setOriginalClearanceFreight(item.getOneClearanceFreight()
                            .subtract(item.getBrandClearanceFeePrice())
                            .subtract(item.getElectrifiedClearanceFeePrice())
                            .subtract(item.getLiquidClearanceFeePrice())
                            .add(item.getDiscountFreightPrice()));
                    item.setAfterDiscountClearanceFreight(item.getOriginalClearanceFreight()
                            .add(item.getBrandClearanceFeePrice())
                            .add(item.getElectrifiedClearanceFeePrice())
                            .add(item.getLiquidClearanceFeePrice())
                            .subtract(item.getDiscountClearanceFeePrice()));
                }
            }
            // 运费原价= 原始价格(无牌无液无电)+特殊加价-优惠
            BigDecimal originalCostSeaFreight = item.getOriginalSeaFreight()
                    .add(item.getBrandFreightPrice())
                    .add(item.getElectrifiedFreightPrice())
                    .add(item.getLiquidFreightPrice())
                    .subtract(item.getDiscountFreightPrice());
            item.setOriginalCostSeaFreight(originalCostSeaFreight);

            // 清关费原价= 原始价格(无牌无液无电)+特殊加价-优惠
            BigDecimal originalCostClearanceFreight =
                    item.getOriginalClearanceFreight()
                            .add(item.getBrandClearanceFeePrice())
                            .add(item.getElectrifiedClearanceFeePrice())
                            .add(item.getLiquidClearanceFeePrice())
                            .subtract(item.getDiscountClearanceFeePrice());
            item.setOriginalCostClearanceFreight(originalCostClearanceFreight);
        }).collect(Collectors.toList());
    }

    @Override
    public List<OrderDO> getOrderList(Collection<Long> ids) {
        return orderMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<OrderDO> getOrderPage(OrderQueryVO query, PageVO page) {
        return orderMapper.selectPage(page, query);
    }

    @Override
    public PageResult<OrderWarehouseAdjustBatchApplyBackVO> orderWarehouseAdjustBatchApplyPage(OrderQueryVO
                                                                                                       query, PageVO page) {

        PageResult<OrderBackPageVO> orderBackPageVOPageResult = this.orderPage(query, page);

        if (orderBackPageVOPageResult != null && CollectionUtil.isNotEmpty(orderBackPageVOPageResult.getList())) {
            PageResult<OrderWarehouseAdjustBatchApplyBackVO> result = new PageResult<>();
            List<OrderBackPageVO> orderBackPageVOList = orderBackPageVOPageResult.getList();

            List<OrderWarehouseAdjustBatchApplyBackVO> orderWarehouseAdjustBatchApplyBackVOS = orderBackPageVOList.stream().map(orderBackPageVO -> {

                OrderWarehouseAdjustBatchApplyBackVO orderWarehouseAdjustBatchApplyBackVO = new OrderWarehouseAdjustBatchApplyBackVO();
                //复制订单数据
                BeanUtils.copyProperties(orderBackPageVO, orderWarehouseAdjustBatchApplyBackVO);

                //TODO yanghao 20220724 详细信息待补充

                return orderWarehouseAdjustBatchApplyBackVO;
            }).collect(Collectors.toList());

            //设置结果集
            result.setList(orderWarehouseAdjustBatchApplyBackVOS);

            //设置页码
            result.setPage(orderBackPageVOPageResult.getPage());
            result.setRows(orderBackPageVOPageResult.getRows());
            result.setPages(orderBackPageVOPageResult.getPages());
            result.setTotal(orderBackPageVOPageResult.getTotal());

            return result;
        }


        return null;
    }

    @Override
    public List<OrderDO> getOrderList(OrderQueryVO query) {
        return orderMapper.selectList(query);
    }

    @Override
    public PageResult<OrderBackPageVO> orderPage(OrderQueryVO query, PageVO page) {
        if (Objects.isNull(query.getLang())) {
            query.setLang(I18nMessage.getLang());
        }
        IPage<OrderBackPageVO> mpPage = MyBatisUtils.buildPage(page);
        long total = orderMapper.orderCount(query);
        log.warn(I18nMessage.getLang().toString());
        int start = (page.getPage() - 1) * page.getRows();
        int size = page.getRows();
        List<OrderBackPageVO> list = orderMapper.orderList(start, size, query);
        return new PageResult<>(list, total, mpPage.getSize(), page.getPage(), (total + mpPage.getSize() - 1) / mpPage.getSize());
    }

    @Override
    public PageResult<OrderBackPageVO> myOrderPage(OrderQueryVO query, PageVO page) {
        if (Objects.isNull(query.getLang())) {
            query.setLang(I18nMessage.getLang());
        }
        IPage<OrderBackPageVO> mpPage = MyBatisUtils.buildPage(page);
        long total = orderMapper.myOrderCount(query);
        log.warn(I18nMessage.getLang().toString());
        int start = (page.getPage() - 1) * page.getRows();
        int size = page.getRows();
        List<OrderBackPageVO> list = orderMapper.myOrderPageList(start, size, query);
        return new PageResult<>(list, total, mpPage.getSize(), page.getPage(), (total + mpPage.getSize() - 1) / mpPage.getSize());
    }


    @Override
    public long orderCount(OrderQueryVO query) {
        return orderMapper.orderCount(query);
    }

    @Override
    public PageResult<OrderBackPageVO> deptOrderPage(OrderQueryVO query, PageVO page) {
        query.setLang(I18nMessage.getLang());
        IPage<OrderBackPageVO> mpPage = MyBatisUtils.buildPage(page);
        long total = orderMapper.deptOrderCount(query);
        log.warn(I18nMessage.getLang().toString());
        int start = (page.getPage() - 1) * page.getRows();
        int size = page.getRows();
        List<OrderBackPageVO> list = orderMapper.deptOrderList(start, size, query);
        return new PageResult<>(list, total, mpPage.getSize(), page.getPage(), (total + mpPage.getSize() - 1) / mpPage.getSize());
    }

    @Override
    public PageResult<OrderBackPageVO> deptOrderPage1(OrderQueryVO query, PageVO page) {
        query.setLang(I18nMessage.getLang());
        IPage<OrderBackPageVO> mpPage = MyBatisUtils.buildPage(page);
        long total = orderMapper.deptOrderCount1(query);
        log.warn(I18nMessage.getLang().toString());
        int start = (page.getPage() - 1) * page.getRows();
        int size = page.getRows();
        List<OrderBackPageVO> list = orderMapper.deptOrderList1(start, size, query);
        return new PageResult<>(list, total, mpPage.getSize(), page.getPage(), (total + mpPage.getSize() - 1) / mpPage.getSize());
    }

    @Override
    public PageResult<OrderBackPageVO> myIssuedOrderPage(OrderQueryVO query, PageVO page) {
        query.setLang(I18nMessage.getLang());
        IPage<OrderBackPageVO> mpPage = MyBatisUtils.buildPage(page);
        long total = orderMapper.appMyIssuedOrderCount(query);
        log.warn(I18nMessage.getLang().toString());
        int start = (page.getPage() - 1) * page.getRows();
        int size = page.getRows();
        List<OrderBackPageVO> list = orderMapper.appMyIssuedOrderList(start, size, query);
        return new PageResult<>(list, total, mpPage.getSize(), page.getPage(), (total + mpPage.getSize() - 1) / mpPage.getSize());
    }

    @Override
    public PageResult<OrderBackPageVO> dynamicOrderPage(OrderQueryVO query, PageVO page) {
        query.setLang(I18nMessage.getLang());
        page.setField("o.order_id");
        IPage<OrderBackPageVO> mpPage = MyBatisUtils.buildPage(page);
        orderMapper.dynamicOrderPage(mpPage, query);
        return PageResult.of(mpPage);
    }

    @Override
    public PageResult<OrderBackPageVO> adminCargoControlOrderPage(OrderQueryVO query, PageVO page) {
        query.setLang(I18nMessage.getLang());
        IPage<OrderBackPageVO> mpPage = MyBatisUtils.buildPage(page);
        long total = orderMapper.adminCargoControlOrderCount(query);
        log.warn(I18nMessage.getLang().toString());
        int start = (page.getPage() - 1) * page.getRows();
        int size = page.getRows();
        List<OrderBackPageVO> list =
                orderMapper.adminCargoControlOrderList(start, size, query);
        return new PageResult<>(list, total, mpPage.getSize(), page.getPage(), (total + mpPage.getSize() - 1) / mpPage.getSize());
    }

    @Override
    public PageResult<OrderBackPageVO> adminCargoControlMyOrderPage(OrderQueryVO query, PageVO page) {
        query.setLang(I18nMessage.getLang());
        IPage<OrderBackPageVO> mpPage = MyBatisUtils.buildPage(page);
        long total = orderMapper.adminCargoControlMyOrderCount(query);
        log.warn(I18nMessage.getLang().toString());
        int start = (page.getPage() - 1) * page.getRows();
        int size = page.getRows();
        List<OrderBackPageVO> list = orderMapper.adminCargoControlMyOrderList(start, size, query);
        return new PageResult<>(list, total, mpPage.getSize(), page.getPage(), (total + mpPage.getSize() - 1) / mpPage.getSize());
    }

    @Override
    public PageResult<OrderBackPageVO> appCargoControlOrderPage(OrderQueryVO query, PageVO page) {
        query.setLang(I18nMessage.getLang());
        IPage<OrderBackPageVO> mpPage = MyBatisUtils.buildPage(page);
        long total = orderMapper.appCargoControlOrderCount(query);
        log.warn(I18nMessage.getLang().toString());
        int start = (page.getPage() - 1) * page.getRows();
        int size = page.getRows();
        List<OrderBackPageVO> list = orderMapper.appCargoControlOrderList(start, size, query);
        return new PageResult<>(list, total, mpPage.getSize(), page.getPage(), (total + mpPage.getSize() - 1) / mpPage.getSize());
    }

    @Override
    public PageResult<OrderBackPageVO> receivedOrderPage(OrderQueryVO query, PageVO page) {
        query.setLang(I18nMessage.getLang());
        page.setField("o.order_id");
        IPage<OrderBackPageVO> mpPage = MyBatisUtils.buildPage(page);
        orderMapper.receivedOrderPage(mpPage, query);
        return PageResult.of(mpPage);
    }

    @Override
    public PageResult<OrderPreloadVO> orderPreloadPage(OrderPreloadReq query) {
        IPage<OrderPreloadVO> mPage = MyBatisUtils.buildPage(query);
        query.setLang(I18nMessage.getLang());
        orderMapper.orderPreloadPage(mPage, query);
        List<OrderPreloadVO> orderList = mPage.getRecords();
        if (CollectionUtil.isEmpty(orderList)) return PageResult.of(mPage);
        List<Long> orderIdList = orderList.stream().map(OrderPreloadVO::getOrderId).collect(Collectors.toList());
        List<OrderItemDO> orderItemList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().in(OrderItemDO::getOrderId, orderIdList));
        List<OrderItemBackVO> orderItemBackList = OrderItemConvert.INSTANCE.convertList(orderItemList);
        Map<Long, List<OrderItemBackVO>> orderItemMap = orderItemBackList.stream().collect(Collectors.groupingBy(OrderItemBackVO::getOrderId));
        orderList.forEach(t -> t.setOrderItemList(orderItemMap.get(t.getOrderId())));
        return PageResult.of(mPage);
    }


    @Override
    public PageResult<OrderBackPageVO> myAllOrderPage(OrderQueryVO query, PageVO page) {
        query.setLang(I18nMessage.getLang());
        IPage<OrderBackPageVO> mpPage = MyBatisUtils.buildPage(page);
        long total = orderMapper.myAllOrderCount(query);
        log.warn(I18nMessage.getLang().toString());
        int start = (page.getPage() - 1) * page.getRows();
        int size = page.getRows();
        List<OrderBackPageVO> list = orderMapper.myAllOrderList(start, size, query);
        return new PageResult<>(list, total, mpPage.getSize(), page.getPage(), (total + mpPage.getSize() - 1) / mpPage.getSize());
    }


    @Override
    public List<OrderPreloadVO> orderPreloadList(OrderPreloadReq query) {
        return orderMapper.orderPreloadList(query);
    }

    @Override
    public List<OrderPreloadVO> orderPreloadListAir(OrderPreloadReq query) {
        return orderMapper.orderPreloadListAir(query);
    }


    @Override
    public PageResult<OrderBackPageVO> pdaOrderWarehouseInPage(PdaOrderQueryVo query, PageVO page) {
        query.setLang(I18nMessage.getLang());
        page.setField("o.order_id");
        IPage<OrderBackPageVO> mpPage = MyBatisUtils.buildPage(page);
        orderMapper.pdaOrderPage(mpPage, query);
        return PageResult.of(mpPage);
    }


    @Override
    public PageResult<OrderBackPageVO> pdaOrderWarehouseAdjustWaitOut(PdaOrderQueryVo query, PageVO page) {
        query.setLang(I18nMessage.getLang());
        page.setField("o.order_id");
        IPage<OrderBackPageVO> mpPage = MyBatisUtils.buildPage(page);
        orderMapper.pdaOrderPage(mpPage, query);
        return PageResult.of(mpPage);
    }


    @Override
    public List<OrderBackPageVO> seasoningCondimentsCargoControlOrderPage(Long orderId, String
            cargoControlPhone, Integer userType) {
        return orderMapper.cargoControlOrderSelect(orderId, cargoControlPhone, userType, I18nMessage.getLang());
    }


    @Override
    public OrderFeeDetailBackVO getOrderFeeDetailById(Long orderId) {
        OrderFeeDetailBackVO orderFeeDetailBackVO = new OrderFeeDetailBackVO();
        OrderDO orderDO = orderMapper.selectById(orderId);
        if (null == orderDO) {
            throw exception(ORDER_NOT_EXISTS);
        }

        orderFeeDetailBackVO.setOrderId(orderId);
        List<String> reslut = new ArrayList<>();

        BigDecimal totalVolume = BigDecimal.ZERO;//总体积

        BigDecimal neeTotalVolume = BigDecimal.ZERO;//預付商品总体积

        BigDecimal needFeeWorth = BigDecimal.ZERO;//预付商品货值

        BigDecimal totalAmountWorth = BigDecimal.ZERO;//总货值

        BigDecimal totalAmount = BigDecimal.ZERO;//总金额

        BigDecimal needTotalAmount = BigDecimal.ZERO;//应收总金额

        BigDecimal wareHouseVolume = BigDecimal.ZERO;//入倉方數

        BigDecimal totalYunfei = BigDecimal.ZERO;//總運費

        BigDecimal totalQingguanfei = BigDecimal.ZERO;//總清關費


        if (StringUtils.isNotBlank(orderDO.getCost())) {
            CostVO costVO = JSONObject.parseObject(orderDO.getCost(), CostVO.class);
            totalAmountWorth = costVO.getTotalWorth();
        }

        orderFeeDetailBackVO.setTotalVolume(orderDO.getSumVolume().toString());//订单总方数
        totalVolume = orderDO.getSumVolume();


        //得到所有币种--后面使用
        Map<Integer, CurrencyRespDTO> currencyDoMap = currencyApi.getAllCurrency();
        //计算预付
        List<ReceivableBackVO> receivableBackVOList = receivableService.getReceivableListByOrderId(orderId);

        //是否已经计算过
        List<Long> orders = new ArrayList<>();


        for (ReceivableBackVO receivableBackVO : receivableBackVOList) {
            BigDecimal receivableFee = (null == receivableBackVO.getTaxAmount() ? BigDecimal.ZERO : receivableBackVO.getTaxAmount());
            receivableFee = receivableFee.subtract((null == receivableBackVO.getDiscountTotal() ? BigDecimal.ZERO : receivableBackVO.getDiscountTotal()));
            if (null != receivableBackVO.getCurrencyId()) {
                CurrencyRespDTO rate = currencyDoMap.get(receivableBackVO.getCurrencyId().intValue());
                if (null != rate && StringUtils.isNotBlank(rate.getFuhao())) {
                    //重新获取汇率-转成RMB
                    ExchangeRateRespDTO rateRespDTO = currencyApi.getCurrencyRateByCode(rate.getFuhao(), "￥");
                    if (null != rateRespDTO && null != rateRespDTO.getCurrencyRate()) {
                        totalAmount = totalAmount.add(receivableFee.multiply(rateRespDTO.getCurrencyRate()));
                        if (null != receivableBackVO.getFeeType() && receivableBackVO.getFeeType() == 1) {
                            totalYunfei = totalYunfei.add(receivableFee.multiply(rateRespDTO.getCurrencyRate()));
                        }
                        if (null != receivableBackVO.getFeeType() && receivableBackVO.getFeeType() == 2) {
                            totalQingguanfei = totalQingguanfei.add(receivableFee.multiply(rateRespDTO.getCurrencyRate()));
                        }
                    }
                }
            }


            //总金额
            if (null == orderFeeDetailBackVO.getTotalAmountList().get(receivableBackVO.getCurrencyId())) {
                orderFeeDetailBackVO.getTotalAmountList().put(receivableBackVO.getCurrencyId(), receivableFee);
            } else {
                BigDecimal tt = orderFeeDetailBackVO.getTotalAmountList().get(receivableBackVO.getCurrencyId());
                orderFeeDetailBackVO.getTotalAmountList().put(receivableBackVO.getCurrencyId(), tt.add(receivableFee));
            }

            //需要预付的货物总体积
            if (1 == receivableBackVO.getIsPayAdvance()) {
                //根据预付拿到当前预付所在的收款单
                if (null != receivableBackVO.getCurrencyId()) {
                    //预付总金额
                    if (null == orderFeeDetailBackVO.getTotalPaymentAmount().get(receivableBackVO.getCurrencyId())) {
                        orderFeeDetailBackVO.getTotalPaymentAmount().put(receivableBackVO.getCurrencyId(), receivableFee);
                    } else {
                        BigDecimal tt = orderFeeDetailBackVO.getTotalPaymentAmount().get(receivableBackVO.getCurrencyId());
                        orderFeeDetailBackVO.getTotalPaymentAmount().put(receivableBackVO.getCurrencyId(), tt.add(receivableFee));
                    }

                    if (null != receivableBackVO.getReceiptId()) {
                        ReceiptDO receiptDO = receiptService.getById(receivableBackVO.getReceiptId());
                        if (null != receiptDO && null != receiptDO.getWriteOffProportion()) {
                            CurrencyRespDTO rate = currencyDoMap.get(receivableBackVO.getCurrencyId().intValue());

                            if (null != rate && StringUtils.isNotBlank(rate.getFuhao())) {
                                //重新获取汇率
                                ExchangeRateRespDTO rateRespDTO = currencyApi.getCurrencyRateByCode(rate.getFuhao(), "￥");
                                if (null != rateRespDTO && null != rateRespDTO.getCurrencyRate()) {
                                    needTotalAmount = needTotalAmount.add(receivableFee.multiply(rateRespDTO.getCurrencyRate()).multiply(BigDecimal.valueOf(receiptDO.getWriteOffProportion().doubleValue() / 100)));
                                }
                            }

                            //已核销预付总金额
                            if (null == orderFeeDetailBackVO.getWriteOffAmount().get(receivableBackVO.getCurrencyId())) {
                                orderFeeDetailBackVO.getWriteOffAmount().put(receivableBackVO.getCurrencyId(), receivableFee.multiply(BigDecimal.valueOf(receiptDO.getWriteOffProportion().doubleValue() / 100)).setScale(2, RoundingMode.HALF_UP));
                            } else {
                                BigDecimal tt = orderFeeDetailBackVO.getWriteOffAmount().get(receivableBackVO.getCurrencyId());
                                orderFeeDetailBackVO.getWriteOffAmount().put(receivableBackVO.getCurrencyId(), tt.add(receivableFee.multiply(BigDecimal.valueOf(receiptDO.getWriteOffProportion().doubleValue() / 100))).setScale(2, RoundingMode.HALF_UP));
                            }
                        }
                    }
                }


              /*
              //已核销预付总金额
                if (2 == receivableBackVO.getStatus()) {
                    if (null == orderFeeDetailBackVO.getWriteOffAmount().get(receivableBackVO.getCurrencyId())) {
                        orderFeeDetailBackVO.getWriteOffAmount().put(receivableBackVO.getCurrencyId(), receivableBackVO.getTotalAmount());
                    } else {
                        BigDecimal tt = orderFeeDetailBackVO.getWriteOffAmount().get(receivableBackVO.getCurrencyId());
                        orderFeeDetailBackVO.getWriteOffAmount().put(receivableBackVO.getCurrencyId(), tt.add(receivableBackVO.getTotalAmount()));
                    }
                }

                if (null != receivableBackVO.getExchangeRate()) {
                    needTotalAmount = needTotalAmount.add(receivableFee.multiply(receivableBackVO.getExchangeRate()));
                } else {
                    if (null != receivableBackVO.getCurrencyId()) {
                        CurrencyRespDTO rate = currencyDoMap.get(receivableBackVO.getCurrencyId());
                        if (null != rate && null != rate.getHuilv()) {
                            needTotalAmount = needTotalAmount.add(receivableFee.multiply((rate.getHuilv().divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP))));
                        }
                    }
                }
                */


                //不需要重复计算
                if (!orders.contains(receivableBackVO.getOrderItemId())) {

                    //neeTotalVolume = neeTotalVolume.add(null == receivableBackVO.getVolume() ? BigDecimal.ZERO : receivableBackVO.getVolume());

                    needFeeWorth = needFeeWorth.add((null == receivableBackVO.getAmountWorth() ? BigDecimal.ZERO : receivableBackVO.getAmountWorth()));

                    //預付商品入倉方數
                    if (Objects.nonNull(receivableBackVO.getOrderItemId())) {
                        OrderItemDO orderItemDO = orderItemMapper.selectById(receivableBackVO.getOrderItemId());
                        if (null != orderItemDO) {
                            if (null != orderItemDO.getWarehouseInInfoVO()) {
                                wareHouseVolume = wareHouseVolume.add(orderItemDO.getWarehouseInInfoVO().getVolume());
                                ////预付商品总体积
                                neeTotalVolume = neeTotalVolume.add(null == orderItemDO.getWarehouseInInfoVO().getVolume() ? BigDecimal.ZERO : orderItemDO.getWarehouseInInfoVO().getVolume());
                            }

                            /*if (null != orderItemDO.getWorthCurrency()) {
                                CurrencyRespDTO worthRate = currencyDoMap.get(orderItemDO.getWorthCurrency().intValue());
                                log.error(worthRate.getFuhao());
                                ExchangeRateRespDTO worthRateDto = currencyApi.getCurrencyRateByCode(worthRate.getFuhao(), "¥");
                                log.error(worthRateDto.toString());
                                //预付商品货值
                                needFeeWorth = needFeeWorth.add((null == orderItemDO.getWorth() ? BigDecimal.ZERO : orderItemDO.getWorth().multiply(worthRateDto.getCurrencyRate())));
                                log.error(needFeeWorth.toString());
                            }*/
                        }
                    }

                }

                orders.add(receivableBackVO.getOrderItemId());

            }

        }

        //应付商品体积占比
        orderFeeDetailBackVO.setPaymentGoodsVolume(neeTotalVolume.setScale(2, RoundingMode.HALF_UP).toString());
        if (totalVolume.compareTo(BigDecimal.ZERO) == 0) {
            orderFeeDetailBackVO.setPaymentGoodsVolumeScale("0");
        } else {
            orderFeeDetailBackVO.setPaymentGoodsVolumeScale(neeTotalVolume.divide(totalVolume, 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP).toString());
        }


        //预付商品货值及占比
        orderFeeDetailBackVO.setPaymentGoodsWorth(needFeeWorth.setScale(2, RoundingMode.HALF_UP).toString());
        if (totalAmountWorth.compareTo(BigDecimal.ZERO) == 0) {
            orderFeeDetailBackVO.setPaymentGoodsWorthScale("0");
        } else {
            orderFeeDetailBackVO.setPaymentGoodsWorthScale(needFeeWorth.divide(totalAmountWorth, 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP).toString());
        }

        //计算已经核销预付金额点比
        if (totalAmount.compareTo(BigDecimal.ZERO) == 0) {
            orderFeeDetailBackVO.setWriteOffAmountScale("0");
        } else {
            orderFeeDetailBackVO.setWriteOffAmountScale(needTotalAmount.divide(totalAmount, 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP).toString());
        }

        //订单下预付商品总方数小于0.5cbm
        if (neeTotalVolume.compareTo(new BigDecimal("0.5")) != 1) {
            reslut.add("pay_total_min");
        }


        if (totalYunfei.compareTo(BigDecimal.ZERO) == 0) {


        } else {
            //已核销预付商品应收明细，超过订单总运费的80%
            if (needTotalAmount.divide(totalYunfei, 4, RoundingMode.HALF_UP).compareTo(new BigDecimal("0.8")) != -1) {
                reslut.add("pay_total_amount");
            }
        }


        //预付商品总入仓方数小于订单所有商品总方数33%
        if ((wareHouseVolume.divide(totalVolume, 4, RoundingMode.HALF_UP)).compareTo(new BigDecimal("0.33")) == -1) {
            reslut.add("pay_volume_scale");
        }


        //总货值>=订单总运费+清关费，当订单总运费+清关费不是RMB，根据系统当前汇率转换成RMB,处理后，日志需记录当前货值和转换后的总海运费+清关费 删除:预付商品货值(needFeeWorth)大于订单总运费+清关费用33%
        BigDecimal yq = totalYunfei.add(totalQingguanfei);

        if (totalAmountWorth.multiply(new BigDecimal("0.3333")).compareTo(yq) == 1) {
            reslut.add("pay_total_fee");
        }

        BigDecimal total1 = totalYunfei.add(totalQingguanfei);


        if (total1.compareTo(BigDecimal.ZERO) == 0) {

        } else {
            //预付商品货值占订单总运费+清关费比例

            //货值三分之一占运费和清关费总和比例
            orderFeeDetailBackVO.setNeedWorthScale(totalAmountWorth.multiply(new BigDecimal("0.3333")).divide(total1, 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100")).toString());
        }


        reslut.add("pending");
        reslut.add("no_pay");


        //根据条件得到处理结果
        orderFeeDetailBackVO.setResult(reslut);

        return orderFeeDetailBackVO;
    }

    @Override
    public PageResult<SearchBackDto> orderNoSearch(String key, PageParam param) {
        IPage<SearchBackDto> mpPage = MyBatisUtils.buildPage(param);
        orderMapper.orderNoSearch(mpPage, key);
        return PageResult.of(mpPage);
    }

    @Override
    public PageResult<SearchBackDto> billNoSearch(String key, PageParam param) {
        IPage<SearchBackDto> mpPage = MyBatisUtils.buildPage(param);
        orderMapper.billNoSearch(mpPage, key);
        return PageResult.of(mpPage);
    }


    @Override
    public PageResult<OrderBackVO> getUnGuanlianOrderPage(OrderQueryVO orderQueryVo, PageVO pageVO) {
        orderQueryVo.setLang(I18nMessage.getLang());
        pageVO.setField("o.order_id");
        IPage<OrderBackVO> mpPage = MyBatisUtils.buildPage(pageVO);
        IPage<OrderBackVO> unGuanlianOrderPage = orderMapper.getUnGuanlianOrderPage(mpPage, orderQueryVo);
        unGuanlianOrderPage.getRecords().forEach(item -> {
            item.setOrderItemVOList(OrderItemConvert.INSTANCE.convertList(orderItemMapper.selectList(OrderItemDO::getOrderId, item.getOrderId())));
        });
        return PageResult.of(mpPage);
    }

    @Override
    public PageResult<OrderDO> getUnMutualOrderPage(OrderQueryVO orderQueryVo, PageVO pageVO) {
        orderQueryVo.setLang(I18nMessage.getLang());
        pageVO.setField("o.order_id");
        IPage<OrderDO> mpPage = MyBatisUtils.buildPage(pageVO);
        IPage<OrderDO> unGuanlianOrderPage = orderMapper.getUnMutualOrderPage(mpPage, orderQueryVo);
        unGuanlianOrderPage.getRecords().forEach(item -> item.setOrderItemDOList(orderItemMapper.selectList(OrderItemDO::getOrderId, item.getOrderId())));
        return PageResult.of(mpPage);
    }

    @Override
    public List<OrderExportBackDTO> getExportOrderList(OrderQueryVO query) {
        query.setLang(I18nMessage.getLang());
        List<OrderExportBackDTO> list = orderMapper.getExportOrderList(query);
        return list;
    }


    @Override
    public List<OrderItemDO> getOrderItemByLineIdAndProductId(Long lineId, Long productId, Long channelId) {
        return orderMapper.getOrderItemByLineIdAndProductId(lineId, productId, channelId);
    }

    @Override
    public List<OrderItemBackVO> getOrderItemInfoListWhenWarehouseInDeleted(Long orderId) {
        List<OrderItemBackVO> infoItemListWhenWarehouseInDeleted = orderItemMapper.getInfoItemListWhenWarehouseInDeleted(orderId, I18nMessage.getLang());

        if (CollectionUtil.isNotEmpty(infoItemListWhenWarehouseInDeleted)) {

            for (OrderItemBackVO orderItemBackVO : infoItemListWhenWarehouseInDeleted) {
                List<OrderWarehouseInDO> warehouseInDeletedList = orderWarehouseInMapper.getDeletedList(orderItemBackVO.getOrderId(), orderItemBackVO.getOrderItemId());
                if (CollectionUtil.isNotEmpty(warehouseInDeletedList)) {
                    orderWarehouseInService.orderItemSetWarehouseInInfoVO(orderItemBackVO, warehouseInDeletedList);
                }
            }
            infoItemListWhenWarehouseInDeleted = fillOrderItemProperties(infoItemListWhenWarehouseInDeleted);

        }
        return infoItemListWhenWarehouseInDeleted;
    }

    @Override
    public OrderPackedPageStatisticsVO orderPackedPageStatistics(Long orderId) {

        OrderPackedPageStatisticsVO statisticsVO = new OrderPackedPageStatisticsVO();

        OrderDO orderDO = orderMapper.getOrderById(orderId);
        statisticsVO.setSumCartonsNumFinishedWarehouseIn(orderDO.getSumCartonsNumFinishedWarehouseIn());
        statisticsVO.setSumQuantityAllFinishedWarehouseIn(orderDO.getSumQuantityAllFinishedWarehouseIn());
        statisticsVO.setSumWeightFinishedWarehouseIn(orderDO.getSumWeightFinishedWarehouseIn());
        statisticsVO.setSumVolumeFinishedWarehouseIn(orderDO.getSumVolumeFinishedWarehouseIn());

        statisticsVO.setSumVolume(orderDO.getSumVolume());
        statisticsVO.setSumWeight(orderDO.getSumWeight());
        statisticsVO.setSumNum(orderDO.getSumNum());
        statisticsVO.setSumQuantity(orderDO.getSumQuantity());

        // 设置填单
        if (StringUtils.isNotBlank(orderDO.getCost())) {
            CostVO costVO = JSONObject.parseObject(orderDO.getCost(), CostVO.class);
            statisticsVO.setSumNumInput(costVO.getTotalNum());
            statisticsVO.setSumQuantityInput(costVO.getTotalQuantity());
            statisticsVO.setSumVolumeInput(costVO.getTotalVolume());
            statisticsVO.setSumWeightInput(costVO.getTotalWeight());
        }

        // 打包数据为空则使用 完成入仓的数据
        statisticsVO.setSumCartonsNumPrevPacked(orderDO.getSumCartonsNumPrevPacked() == null ? orderDO.getSumCartonsNumFinishedWarehouseIn() : orderDO.getSumCartonsNumPrevPacked());
        statisticsVO.setSumQuantityAllPrevPacked(orderDO.getSumQuantityAllPrevPacked() == null ? orderDO.getSumQuantityAllFinishedWarehouseIn() : orderDO.getSumQuantityAllPrevPacked());
        statisticsVO.setSumVolumePrevPacked(orderDO.getSumVolumePrevPacked() == null ? orderDO.getSumVolumeFinishedWarehouseIn() : orderDO.getSumVolumePrevPacked());
        statisticsVO.setSumWeightPrevPacked(orderDO.getSumWeightPrevPacked() == null ? orderDO.getSumWeightFinishedWarehouseIn() : orderDO.getSumWeightPrevPacked());

        return statisticsVO;
    }

    @Override
    public Integer getAllProcessingApprovalCount(Long orderId) {
        return orderMapper.getWaitApprovalCount(orderId);
    }

    @Override
    public void throwPendingExceptionOrProcessingApproval(Long orderId) {
        OrderDO orderDO = orderMapper.selectById(orderId);
        if (orderDO == null) {
            throw exception(ORDER_NOT_EXISTS);
        }

        //有未处理的异常
//        List<OrderExceptionDO> exceptionList = orderExceptionService.getPendingOrderExceptionByOrderIdAndOrderItemIdAndExceptionKey(orderId, null, null);
//        if (CollectionUtil.isNotEmpty(exceptionList)) {
        if (orderDO.getAbnormalState() != 0) {
            throw exception(ORDER_HAS_PENDING_EXCEPTION, orderDO.getOrderNo());
        }

        //判断未处理审核
//        this.throwProcessingApproval(orderId);
    }

    @Override
    public void throwProcessingApproval(Long orderId, OrderApprovalTypeEnum approvalTypeEnum) {
        OrderDO orderDO = orderMapper.selectById(orderId);
        if (orderDO == null) {
            throw exception(ORDER_NOT_EXISTS);
        }
        OrderApprovalTypeCheckEvent approvalTypeCheckEvent = new OrderApprovalTypeCheckEvent(orderDO.getOrderId(), null, approvalTypeEnum.getValue(), null, false);
        applicationContext.publishEvent(approvalTypeCheckEvent);
        if (approvalTypeCheckEvent.getResult()) {
            throw exception(ORDER_HAS_PROCESSING_APPROVAL, orderDO.getOrderNo());
        }
    }


    @Override
    public String getEarliestBoxTime(Long customerId) {
        return orderMapper.getEarliestBoxTime(customerId);
    }

    @Override
    public Long getOrderConsigneeMemberInfo(Long orderId) {
        return orderMapper.getOrderConsigneeMemberInfo(orderId);
    }


    @Override
    public List<OrderDO> getOrderChildren(Long parentOrderId) {
        return orderMapper.selectList(new LambdaQueryWrapperX<OrderDO>().eq(OrderDO::getParentOrderId, parentOrderId));
    }

    @Override
    public List<OrderDO> getOrderChildren(List<Long> orderIds) {
        return orderMapper.selectList(new LambdaQueryWrapperX<OrderDO>().in(OrderDO::getOrderId, orderIds));
    }

    @Override
    public StatisticsOrderVO statisticsOrder(OrderQueryVO query) {
        StatisticsOrderVO vo = orderMapper.statisticsOrder(query);
        if (Objects.nonNull(vo)) {
            vo.setTotalVolume(new BigDecimal(vo.getTotalVolume()).setScale(2, RoundingMode.HALF_UP).toString());
            vo.setTotalWeight(new BigDecimal(vo.getTotalWeight()).setScale(2, RoundingMode.HALF_UP).toString());
            vo.setTotalWVolume(new BigDecimal(vo.getTotalWVolume()).setScale(2, RoundingMode.HALF_UP).toString());
            vo.setTotalVWeight(new BigDecimal(vo.getTotalVWeight()).setScale(2, RoundingMode.HALF_UP).toString());
            vo.setTotalChargeVolume(new BigDecimal(vo.getTotalChargeVolume()).setScale(2, RoundingMode.HALF_UP).toString());
            vo.setTotalChargeWeight(new BigDecimal(vo.getTotalChargeWeight()).setScale(2, RoundingMode.HALF_UP).toString());
        } else {
            vo = new StatisticsOrderVO();
        }
//        if (Objects.nonNull(query.getBeginWarehouseInTime()) && Objects.nonNull(query.getEndWarehouseInTime())) {
//            // 入仓记录统计时，实测入仓数据替换为入仓记录中的和值
//            StatisticsOrderVO warehouseInVO = orderMapper.statisticsWarehouseIn(query);
//            if (Objects.nonNull(warehouseInVO)) {
//                vo.setTotalNum(warehouseInVO.getTotalNum());
//                vo.setTotalVolume(new BigDecimal(warehouseInVO.getTotalVolume()).setScale(2, RoundingMode.HALF_UP).toString());
//                vo.setTotalWeight(new BigDecimal(warehouseInVO.getTotalWeight()).setScale(2, RoundingMode.HALF_UP).toString());
//                vo.setOrderQuantity(warehouseInVO.getOrderQuantity());
//            } else {
//                vo.setTotalNum(0);
//                vo.setTotalVolume(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP).toString());
//                vo.setTotalWeight(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP).toString());
//                vo.setOrderQuantity(0);
//            }
//        }
//        if (Objects.nonNull(query.getBeginRucangTime()) && Objects.nonNull(query.getEndRucangTime())) {
//            // 入仓记录统计时，实测入仓数据替换为入仓记录中的和值
//            StatisticsOrderVO warehouseInVO = orderMapper.statisticsWarehouseIn(query);
//            if (Objects.nonNull(warehouseInVO)) {
//                vo.setTotalNum(warehouseInVO.getTotalNum());
//                vo.setTotalVolume(new BigDecimal(warehouseInVO.getTotalVolume()).setScale(2, RoundingMode.HALF_UP).toString());
//                vo.setTotalWeight(new BigDecimal(warehouseInVO.getTotalWeight()).setScale(2, RoundingMode.HALF_UP).toString());
//                vo.setOrderQuantity(warehouseInVO.getOrderQuantity());
//            } else {
//                vo.setTotalNum(0);
//                vo.setTotalVolume(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP).toString());
//                vo.setTotalWeight(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP).toString());
//                vo.setOrderQuantity(0);
//            }
//        }
        if (Objects.nonNull(query.getBeginPickUpTime()) && Objects.nonNull(query.getEndPickUpTime())) {
            // 入仓记录统计时，实测入仓数据替换为入仓记录中的和值
            StatisticsOrderVO pickUpVO = orderMapper.statisticsPickUp(query);
            if (Objects.nonNull(pickUpVO)) {
                vo.setTotalNum(pickUpVO.getTotalNum());
            } else {
                vo.setTotalNum(0);
            }
        }
        return vo;
    }

    @Override
    public StatisticsOrderVO statisticsMyOrder(OrderQueryVO query) {
        StatisticsOrderVO vo = orderMapper.statisticsMyOrder(query);
        if (Objects.nonNull(vo)) {
            vo.setTotalVolume(new BigDecimal(vo.getTotalVolume()).setScale(2, RoundingMode.HALF_UP).toString());
            vo.setTotalWeight(new BigDecimal(vo.getTotalWeight()).setScale(2, RoundingMode.HALF_UP).toString());
            vo.setTotalWVolume(new BigDecimal(vo.getTotalWVolume()).setScale(2, RoundingMode.HALF_UP).toString());
            vo.setTotalVWeight(new BigDecimal(vo.getTotalVWeight()).setScale(2, RoundingMode.HALF_UP).toString());
            vo.setTotalChargeVolume(new BigDecimal(vo.getTotalChargeVolume()).setScale(2, RoundingMode.HALF_UP).toString());
            vo.setTotalChargeWeight(new BigDecimal(vo.getTotalChargeWeight()).setScale(2, RoundingMode.HALF_UP).toString());
        } else {
            vo = new StatisticsOrderVO();
        }
//        if (Objects.nonNull(query.getBeginWarehouseInTime()) && Objects.nonNull(query.getEndWarehouseInTime())) {
//            // 入仓记录统计时，实测入仓数据替换为入仓记录中的和值
//            StatisticsOrderVO warehouseInVO = orderMapper.statisticsWarehouseIn(query);
//            if (Objects.nonNull(warehouseInVO)) {
//                vo.setTotalNum(warehouseInVO.getTotalNum());
//                vo.setTotalVolume(new BigDecimal(warehouseInVO.getTotalVolume()).setScale(2, RoundingMode.HALF_UP).toString());
//                vo.setTotalWeight(new BigDecimal(warehouseInVO.getTotalWeight()).setScale(2, RoundingMode.HALF_UP).toString());
//                vo.setOrderQuantity(warehouseInVO.getOrderQuantity());
//            } else {
//                vo.setTotalNum(0);
//                vo.setTotalVolume(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP).toString());
//                vo.setTotalWeight(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP).toString());
//                vo.setOrderQuantity(0);
//            }
//        }
//        if (Objects.nonNull(query.getBeginRucangTime()) && Objects.nonNull(query.getEndRucangTime())) {
//            // 入仓记录统计时，实测入仓数据替换为入仓记录中的和值
//            StatisticsOrderVO warehouseInVO = orderMapper.statisticsMyWarehouseIn(query);
//            if (Objects.nonNull(warehouseInVO)) {
//                vo.setTotalNum(warehouseInVO.getTotalNum());
//                vo.setTotalVolume(new BigDecimal(warehouseInVO.getTotalVolume()).setScale(2, RoundingMode.HALF_UP).toString());
//                vo.setTotalWeight(new BigDecimal(warehouseInVO.getTotalWeight()).setScale(2, RoundingMode.HALF_UP).toString());
//                vo.setOrderQuantity(warehouseInVO.getOrderQuantity());
//            } else {
//                vo.setTotalNum(0);
//                vo.setTotalVolume(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP).toString());
//                vo.setTotalWeight(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP).toString());
//                vo.setOrderQuantity(0);
//            }
//        }
        if (Objects.nonNull(query.getBeginPickUpTime()) &&
                Objects.nonNull(query.getEndPickUpTime())) {
            // 提货记录统计时，实测入仓数据替换为提货记录中的和值
            StatisticsOrderVO pickUpVO = orderMapper.statisticsPickUp(query);
            if (Objects.nonNull(pickUpVO)) {
                vo.setTotalNum(pickUpVO.getTotalNum());
            } else {
                vo.setTotalNum(0);
            }
        }
        return vo;
    }

    @Override
    public void exportOrderExcel(HttpServletResponse response, OrderQueryVO query) throws IOException {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATA_FORMAT);
        String nowTime = formatter.format(LocalDateTime.now());

        response.setContentType(CONTENT_TYPE);
        //设置字符集为utf-8
        response.setCharacterEncoding(CHARACTER_UTF_8);
        String sheetName = I18nMessage.getLang() == 0 ? "订单管理第{0}页" : "Order Management number {0}";
        String fileName = sheetName.concat("_").concat(nowTime).concat(".xlsx");

        //文件名乱码解决：用postman测正常，浏览器多了filename_=utf-8等字样
        response.setHeader(CONTENT_DISPOSITION,
                "attachment;filename=" + URLEncoder.encode(fileName, CHARACTER_UTF_8)
                        + ";filename*=utf-8''" + URLEncoder.encode(fileName, CHARACTER_UTF_8));

        //发送一个报头，告诉浏览器当前页面不进行缓存，每次访问的时间必须从服务器上读取最新的数据
        response.setHeader(CACHE_CONTROL, NO_STORE);
        response.addHeader(CACHE_CONTROL, MAX_AGE);

        ServletOutputStream out = response.getOutputStream();

        ExcelWriter excelWriter = EasyExcel.write(out, OrderExcelVO.class).inMemory(true).build();
        query.setLang(I18nMessage.getLang());
        PageVO page = new PageVO();
        page.setField("o.order_id");
        long total = orderMapper.exportOrderExcelCount(query);
        int pageNumber = (int) Math.ceil((double) total / (double) PAGE_SIZE);    //分页条数看情况
        // 去调用写入,根据数据库分页的总的页数来
        for (int i = 1; i <= pageNumber; i++) {
            // 根据最大查询值配置来进行sheet分页
            WriteSheet writeSheet = EasyExcel.writerSheet(MessageFormat.format(sheetName, i)).registerWriteHandler(new WaterMarkHandler("捷道机密文件，禁止传播")).build();
            //先定义一个空集合每次循环使他变成null减少内存的占用
            int start = (i - 1) * PAGE_SIZE;
            int end = i * PAGE_SIZE;
            query.setLang(I18nMessage.getLang());
            page.setField("o.order_id");
            List<OrderExcelVO> pageList = orderMapper.exportOrderExcelList(start, end, query).stream().peek(excData -> {
                WarehouseInInfoVO warehouseInInfoVO = excData.getWarehouseInInfoVO();
                if (Objects.nonNull(warehouseInInfoVO)) {
                    List<OrderLocationMergeVO> orderLocationSet = warehouseInInfoVO.getOrderLocationMergeVOSet();
                    String storageLocation = "";
                    if (CollectionUtil.isNotEmpty(orderLocationSet)) {
                        for (OrderLocationMergeVO vo : orderLocationSet) {
                            if (StringUtils.isBlank(storageLocation)) {
                                storageLocation = vo.getAreaName() + vo.getLocationName();
                            } else {
                                storageLocation = storageLocation + "," + vo.getAreaName() + vo.getLocationName();
                            }
                        }
                    }
                    excData.setStorageLocation(storageLocation);
                }
                String consignorPhone = "+" + excData.getConsignorCountryCode() + excData.getConsignorPhone();
                String consigneePhone = "+" + excData.getConsigneeCountryCode() + excData.getConsigneePhone();
                excData.setConsignorPhone(consignorPhone);
                excData.setConsigneePhone(consigneePhone);
            }).collect(Collectors.toList());
            excelWriter.write(pageList, writeSheet);
            pageList.clear();
        }

        // 千万别忘记finish 会帮忙关闭流
        excelWriter.finish();
        out.flush();
    }

    @Override
    public FileDO makeOrderExcelFile(Long userId, Integer userType, OrderQueryVO query) throws Exception {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATA_FORMAT);
        String nowTime = formatter.format(LocalDateTime.now());

        String sheetName = query.getLang() == 0 ? "订单管理第{0}页" : "Order Management number {0}";
        if (Objects.isNull(userId)) {
            userId = 0L;
        }
        if (Objects.isNull(userType)) {
            userType = 2;
        }
        String fileName = userId.toString().concat(StrUtil.DASHED).concat(userType.toString()).concat(StrUtil.DASHED).concat(nowTime).concat(".xlsx");
        String dir = ueProperties.getTempDir().concat("/excel/");
        // 创建需要写入的文件目录
        File fileDir = new File(dir);
        if (!fileDir.exists()) {
            // 不存在则创建一个目录
            fileDir.mkdirs();
        }
        String path = dir + fileName;
        // 创建写入的输出流
        OutputStream out = new FileOutputStream(path);
        ExcelWriter excelWriter = EasyExcel.write(out, OrderExcelVO.class).inMemory(true).build();
        PageVO page = new PageVO();
        page.setField("o.order_id");
        long total = orderMapper.exportOrderExcelCount(query);
        int pageNumber = (int) Math.ceil((double) total / (double) PAGE_SIZE);    //分页条数看情况
        // 去调用写入,根据数据库分页的总的页数来
        for (int i = 1; i <= pageNumber; i++) {
            // 根据最大查询值配置来进行sheet分页
            WriteSheet writeSheet = EasyExcel.writerSheet(MessageFormat.format(sheetName, i)).registerWriteHandler(new WaterMarkHandler("捷道机密文件，禁止传播")).build();
            //先定义一个空集合每次循环使他变成null减少内存的占用
            int start = (i - 1) * PAGE_SIZE;
            int end = i * PAGE_SIZE;
            page.setField("o.order_id");
            List<OrderExcelVO> pageList = orderMapper.exportOrderExcelList(start, end, query).stream().peek(excData -> {
                WarehouseInInfoVO warehouseInInfoVO = excData.getWarehouseInInfoVO();
                if (Objects.nonNull(warehouseInInfoVO)) {
                    List<OrderLocationMergeVO> orderLocationSet = warehouseInInfoVO.getOrderLocationMergeVOSet();
                    String storageLocation = "";
                    if (CollectionUtil.isNotEmpty(orderLocationSet)) {
                        for (OrderLocationMergeVO vo : orderLocationSet) {
                            if (StringUtils.isBlank(storageLocation)) {
                                storageLocation = vo.getAreaName() + vo.getLocationName();
                            } else {
                                storageLocation = storageLocation + "," + vo.getAreaName() + vo.getLocationName();
                            }
                        }
                    }
                    excData.setStorageLocation(storageLocation);
                }
                String consignorPhone = "+" + excData.getConsignorCountryCode() + excData.getConsignorPhone();
                String consigneePhone = "+" + excData.getConsigneeCountryCode() + excData.getConsigneePhone();
                excData.setConsignorPhone(consignorPhone);
                excData.setConsigneePhone(consigneePhone);
            }).collect(Collectors.toList());
            excelWriter.write(pageList, writeSheet);
            pageList.clear();
        }
        // 千万别忘记finish 会帮忙关闭流
        excelWriter.finish();
        out.flush();
        // 获取到临时文件
        File file = new File(path);
        // 创建FileInputStream对象
        FileInputStream fileInputStream = new FileInputStream(file);
        // 读取文件内容
        byte[] fileBytes = new byte[(int) file.length()];
        fileInputStream.read(fileBytes);
        // 关闭文件流
        fileInputStream.close();
        // 将文件上传到资源服务器
        FileDO fileDO = fileService.createFile(dir, fileName, fileBytes);
        // 删除临时文件
        FileUtil.del(file);
        fileDO.setFileName(fileName);
        return fileDO;
    }


    @Override
    public FileDO makeMyOrderExcelFile(Long userId, Integer userType, OrderQueryVO query) throws Exception {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATA_FORMAT);
        String nowTime = formatter.format(LocalDateTime.now());
        String sheetName = query.getLang() == 0 ? "订单管理第{0}页" : "Order Management number {0}";
        if (Objects.isNull(userId)) {
            userId = 0L;
        }
        if (Objects.isNull(userType)) {
            userType = 2;
        }
        String fileName = userId.toString().concat(StrUtil.DASHED).concat(userType.toString()).concat(StrUtil.DASHED).concat(nowTime).concat(".xlsx");
        String dir = ueProperties.getTempDir().concat("/excel/");
        // 创建需要写入的文件目录
        File fileDir = new File(dir);
        if (!fileDir.exists()) {
            // 不存在则创建一个目录
            fileDir.mkdirs();
        }
        String path = dir + fileName;
        // 创建写入的输出流
        OutputStream out = new FileOutputStream(path);
        ExcelWriter excelWriter = EasyExcel.write(out, OrderExcelVO.class).inMemory(true).build();
        PageVO page = new PageVO();
        page.setField("o.order_id");
        long total = orderMapper.exportMyOrderExcelCount(query);
        int pageNumber = (int) Math.ceil((double) total / (double) PAGE_SIZE);    //分页条数看情况
        // 去调用写入,根据数据库分页的总的页数来
        for (int i = 1; i <= pageNumber; i++) {
            // 根据最大查询值配置来进行sheet分页
            WriteSheet writeSheet = EasyExcel.writerSheet(MessageFormat.format(sheetName, i)).registerWriteHandler(new WaterMarkHandler("捷道机密文件，禁止传播")).build();
            //先定义一个空集合每次循环使他变成null减少内存的占用
            int start = (i - 1) * PAGE_SIZE;
            int end = i * PAGE_SIZE;
            page.setField("o.order_id");
            List<OrderExcelVO> pageList = orderMapper.exportMyOrderExcelList(start, end, query).stream().peek(excData -> {
                WarehouseInInfoVO warehouseInInfoVO = excData.getWarehouseInInfoVO();
                if (Objects.nonNull(warehouseInInfoVO)) {
                    List<OrderLocationMergeVO> orderLocationSet = warehouseInInfoVO.getOrderLocationMergeVOSet();
                    String storageLocation = "";
                    if (CollectionUtil.isNotEmpty(orderLocationSet)) {
                        for (OrderLocationMergeVO vo : orderLocationSet) {
                            if (StringUtils.isBlank(storageLocation)) {
                                storageLocation = vo.getAreaName() + vo.getLocationName();
                            } else {
                                storageLocation = storageLocation + "," + vo.getAreaName() + vo.getLocationName();
                            }
                        }
                    }
                    excData.setStorageLocation(storageLocation);
                }
                String consignorPhone = "+" + excData.getConsignorCountryCode() + excData.getConsignorPhone();
                String consigneePhone = "+" + excData.getConsigneeCountryCode() + excData.getConsigneePhone();
                excData.setConsignorPhone(consignorPhone);
                excData.setConsigneePhone(consigneePhone);
            }).collect(Collectors.toList());
            excelWriter.write(pageList, writeSheet);
            pageList.clear();
        }
        // 千万别忘记finish 会帮忙关闭流
        excelWriter.finish();
        out.flush();
        // 获取到临时文件
        File file = new File(path);
        // 创建FileInputStream对象
        FileInputStream fileInputStream = new FileInputStream(file);
        // 读取文件内容
        byte[] fileBytes = new byte[(int) file.length()];
        fileInputStream.read(fileBytes);
        // 关闭文件流
        fileInputStream.close();
        // 将文件上传到资源服务器
        FileDO fileDO = fileService.createFile(dir, fileName, fileBytes);
        // 删除临时文件
        FileUtil.del(file);
        fileDO.setFileName(fileName);
        return fileDO;
    }

    /**
     * 获取异常单统计信息
     *
     * @return
     */
    @Override
    public List<OrderExceptionStatisticsExcelVo> getOrderExceptionStatisticsExcel(OrderQueryVO query) {
        return orderMapper.getOrderExceptionStatisticsList(query);
    }

    /**
     * 获取重货统计信息
     *
     * @return
     */
    @Override
    public List<OrderHeavyExcelVo> getHeavyOrderExcelList(OrderQueryVO query) {
        return orderMapper.getHeavyOrderExcelList(query);
    }

    /**
     * 获取腿仓单统计
     *
     * @param query
     * @return
     */
    @Override
    public List<OrderReturnOrderExcelVo> getReturnOrderExcelList(OrderQueryVO query) {
        return orderMapper.getReturnOrderExcelList(query);
    }

    /**
     * 获取售后赔偿
     *
     * @param query
     * @return
     */
    @Override
    public List<OrderSaleRepayExcelVo> getSaleRepayExcelList(OrderQueryVO query) {
        return orderMapper.getSaleRepayExcelList(query);
    }

    /**
     * 获取报关数据
     *
     * @param query
     * @return
     */
    @Override
    public List<OrderCustomsDatasExcelVo> getCustomsDatasExcelList(OrderQueryVO query) {
        return orderMapper.getCustomsDatasExcelList(query);
    }

    /**
     * 获取客户出货量
     *
     * @param query
     * @return
     */
    @Override
    public List<OrderShipDataExcelVo> getShipDatasExcelList(OrderQueryVO query) {
        return orderMapper.getShipDatasExcelList(query);
    }

    /**
     * 获取预付运费
     *
     * @param query
     * @return
     */
    @Override
    public List<OrderShipFeeExcelVo> getShipFeeExcelList(OrderQueryVO query) {
        return orderMapper.getShipFeeExcelList(query);
    }


    @Override
    public OrderCertificateVO certificateSearch(String key) {
        if (StringUtils.isEmpty(key)) {
            throw new ServiceException(500, "搜索条件不能为空");
        }
        OrderDO orderDO = orderMapper.selectOne(new LambdaQueryWrapper<OrderDO>()
                .and(wrapper -> wrapper.eq(OrderDO::getOrderNo, key).or().eq(OrderDO::getMarks, key))
                .last("limit 1")
        );

        if (orderDO == null) {
            int position = key.lastIndexOf("-");
            if (position > 0) {
                String orderNo = key.substring(0, position);
                orderDO = orderMapper.selectOne(new LambdaQueryWrapper<OrderDO>()
                        .eq(OrderDO::getOrderNo, orderNo)
                        .last("limit 1")
                );
            }
        }

        if (orderDO == null) {
            throw new ServiceException(500, "订单不存在");
        }

        OrderCertificateVO orderCertificateVO = new OrderCertificateVO();
        orderCertificateVO.setOrderId(orderDO.getOrderId());
        orderCertificateVO.setOrderNo(orderDO.getOrderNo());
        orderCertificateVO.setMarks(orderDO.getMarks());
        //发货人表查找
        OrderConsignorDO consignorDO = orderConsignorService.getOne(new LambdaQueryWrapperX<OrderConsignorDO>()
                .eq(OrderConsignorDO::getOrderId, orderDO.getOrderId())
                .last("limit 1")
        );
        if (consignorDO == null) {
            return orderCertificateVO;
        }

        Long customerId = consignorDO.getCustomerId();
        CustomerDO customerDO = customerService.getCustomer(customerId);
        if (customerDO != null && StringUtils.isNotEmpty(customerDO.getCarNo())) {
            OrderCertificateVO.IDCardInfo cardInfo = new OrderCertificateVO.IDCardInfo();
            cardInfo.setCardName(customerDO.getCarName());
            cardInfo.setCardNo(customerDO.getCarNo());
            cardInfo.setPhone(consignorDO.getPhone());
            orderCertificateVO.setCardInfo(cardInfo);
        } else {
            OrderCertificateVO.IDCardInfo cardInfo = new OrderCertificateVO.IDCardInfo();
            cardInfo.setPhone(consignorDO.getPhone());
            orderCertificateVO.setCardInfo(cardInfo);
        }
        //收货人
        OrderConsigneeDO consigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapperX<OrderConsigneeDO>()
                .eq(OrderConsigneeDO::getOrderId, orderDO.getOrderId())
                .last("limit 1")
        );
        if (consigneeDO == null) {
            return orderCertificateVO;
        }

        Long customerId2 = consigneeDO.getCustomerId();
        CustomerDO customerDO2 = customerService.getCustomer(customerId2);
        if (customerDO2 != null && StringUtils.isNotEmpty(customerDO2.getCarNo())) {
            OrderCertificateVO.IDCardInfo cardInfo = new OrderCertificateVO.IDCardInfo();
            cardInfo.setCardName(customerDO2.getCarName());
            cardInfo.setCardNo(customerDO2.getCarNo());
            cardInfo.setPhone(consigneeDO.getPhone());
            orderCertificateVO.setConsigneeInfo(cardInfo);
        } else {
            OrderCertificateVO.IDCardInfo cardInfo = new OrderCertificateVO.IDCardInfo();
            cardInfo.setPhone(consigneeDO.getPhone());
            orderCertificateVO.setConsigneeInfo(cardInfo);
        }
        return orderCertificateVO;
    }

    /**
     * 校验控货
     *
     * @param kycReqVO
     * @return
     */
    @Override
    public Boolean checkKycStatus(OrderKycReqVO kycReqVO, Long userId) {
        if (Objects.isNull(kycReqVO)) {
            throw exception(GlobalErrorCodeConstants.BAD_REQUEST);
        }
        // 非控货订单不用校验
        if (!kycReqVO.getControlCargoStatus()) {
            return true;
        }

        //根据线路ID获取当前始发仓需要kyc状态
        LogisticsInfoDto logisticsInfoDto = warehouseLineMapper.getStartInfoAndDestInfoByLineId(kycReqVO.getLineId());

        if (Objects.isNull(logisticsInfoDto)) {
            throw exception(ORDER_LINE_NOT_EXIST);
        }

        Integer kycStatus = logisticsInfoDto.getKycStatus();
        // 1:无需认证 2: 身份证实名 3: 营业执照实名 4: 身份证与营业执照实名 5: 身份证或营业执照实名

        if (userId == null || userId == 0) {
            throw exception(USER_NOT_EXISTS);
        }
        //获取当前用户身份证认证状态和营业执照状态
        UserCardAuthDO userCardAuthDO = userCardAuthService.getOne(new LambdaQueryWrapperX<UserCardAuthDO>().eq(UserCardAuthDO::getUserId, userId));
        UserEnterpriseAuthDO userEnterpriseAuthDO = userEnterpriseAuthService.getOne(new LambdaQueryWrapperX<UserEnterpriseAuthDO>().eq(UserEnterpriseAuthDO::getUserId, userId));

        switch (kycStatus) {
            case 1:
                // 无需认证
                return true;
            case 2:
                // 仅身份证
                if (!Objects.isNull(userCardAuthDO) && userCardAuthDO.getStatus() == 2) {
                    return true;
                } else {
                    throw exception(ORDER_NEED_PERSONAL_KYC);
                }
            case 3:
                //仅营业执照
                if (!Objects.isNull(userEnterpriseAuthDO) && userEnterpriseAuthDO.getStatus() == 2) {
                    return true;
                } else {
                    throw exception(ORDER_NEED_COMPANY_KYC);
                }
            case 4:
                //身份证和营业执照
                if (Objects.isNull(userCardAuthDO) || userCardAuthDO.getStatus() != 2) {
                    throw exception(ORDER_NEED_PERSONAL_KYC);
                } else if (Objects.isNull(userEnterpriseAuthDO) || userEnterpriseAuthDO.getStatus() != 2) {
                    throw exception(ORDER_NEED_COMPANY_KYC);
                } else {
                    return true;
                }
            case 5:
                //身份证或营业执照
                if ((!Objects.isNull(userCardAuthDO) && userCardAuthDO.getStatus() == 2) || (!Objects.isNull(userEnterpriseAuthDO) && userEnterpriseAuthDO.getStatus() == 2)) {
                    return true;
                } else {
                    throw exception(ORDER_NEED_COMPANY_KYC);
                }
            default:
                throw exception(GlobalErrorCodeConstants.BAD_REQUEST);
        }
    }

    @Override
    public OrderKycRespVo getKycStatus(OrderKycReqVO kycReqVO, Long userId) {
        OrderKycRespVo respVo = new OrderKycRespVo();
        if (Objects.isNull(kycReqVO)) {
            throw exception(GlobalErrorCodeConstants.BAD_REQUEST);
        }
        //控货订单不用校验
       /* if(!kycReqVO.getControlCargoStatus()){
            return respVo;
        }*/

        //根据线路ID获取当前始发仓需要kyc状态
        LogisticsInfoDto logisticsInfoDto = warehouseLineMapper.getStartInfoAndDestInfoByLineId(kycReqVO.getLineId());

        if (Objects.isNull(logisticsInfoDto)) {
            throw exception(ORDER_LINE_NOT_EXIST);
        }


        // 1:无需认证 2: 身份证实名 3: 营业执照实名 4: 身份证与营业执照实名 5: 身份证或营业执照实名

        if (userId == null || userId == 0) {
            throw exception(USER_NOT_EXISTS);
        }
        //获取当前用户身份证认证状态和营业执照状态
        UserCardAuthDO userCardAuthDO = userCardAuthService.getOne(new LambdaQueryWrapperX<UserCardAuthDO>().eq(UserCardAuthDO::getUserId, userId));
        UserEnterpriseAuthDO userEnterpriseAuthDO = userEnterpriseAuthService.getOne(new LambdaQueryWrapperX<UserEnterpriseAuthDO>().eq(UserEnterpriseAuthDO::getUserId, userId));

        Integer kycStatus = logisticsInfoDto.getKycStatus();
        respVo.setWareHouseStatus(kycStatus);
        if (!Objects.isNull(userCardAuthDO)) {
            respVo.setMemberKycStatus(userCardAuthDO.getStatus());
        }
        if (!Objects.isNull(userEnterpriseAuthDO)) {
            respVo.setCompanyKycStatus(userEnterpriseAuthDO.getStatus());
        }

        return respVo;
    }

    @Override
    public List<OrderDO> commissionOrderList() {
        return orderMapper.commissionOrderList();
    }

    @Override
    public OrderDO getOrderById(Long orderId) {
        return orderMapper.getOrderById(orderId);
    }

    @Override
    public void orderChildren(Long parentOrderId, List<OrderDO> orderChildrenList) {
        List<OrderDO> orderDOList = orderMapper.orderChildren(parentOrderId);
        if (CollectionUtil.isNotEmpty(orderDOList)) {
            for (OrderDO orderDO : orderDOList) {
                if (!orderChildrenList.contains(orderDO)) {
                    orderChildrenList.add(orderDO);
                    orderChildren(orderDO.getOrderId(), orderChildrenList);
                }
            }
        }
    }

    @Override
    public List<OrderDO> getNoConsigeeCustomerOrderList(Integer day) {
        return orderMapper.getNoConsigeeCustomerOrderList(day);
    }


    @Override
    public List<OrderDO> getOrderChildrenLikeByOrderNo(String orderNoLike) {
        return orderMapper.getOrderChildrenLikeByOrderNo(orderNoLike);
    }

    @Override
    public String getDestCountryByOrderId(Long orderId) {
        return orderMapper.getDestCountryByOrderId(orderId);
    }

    @Override
    public ContainerNumberSummaryDto orderSummaryByDestRegionAndOrderIds(RegionDO destRegion, Collection<Long> orderIds) {
        if (Objects.isNull(destRegion)) {
            throw exception(NOT_FIND_DEST_REGION);
        }
        if (Objects.isNull(destRegion.getImportCurrency1()) || StringUtils.equals(destRegion.getImportCurrency1(), "0")) {
            throw exception(DEST_REGION_FREIGHT_CURRENCY_NOT_NULL, I18nMessage.getLang() == 0 ? destRegion.getTitleZh() : destRegion.getTitleEn());
        }
        if (Objects.isNull(destRegion.getImportCurrency2()) || StringUtils.equals(destRegion.getImportCurrency2(), "0")) {
            throw exception(DEST_REGION_CLEARANCE_CURRENCY_NOT_NULL, I18nMessage.getLang() == 0 ? destRegion.getTitleZh() : destRegion.getTitleEn());
        }
        if (Objects.isNull(destRegion.getImportCurrency1()) || StringUtils.equals(destRegion.getImportCurrency1(), "0")) {
            throw exception(DEST_REGION_MAIN_OTHER_CURRENCY_NOT_NULL, I18nMessage.getLang() == 0 ? destRegion.getTitleZh() : destRegion.getTitleEn());
        }
        if (Objects.isNull(destRegion.getImportCurrency1()) || StringUtils.equals(destRegion.getImportCurrency1(), "0")) {
            throw exception(DEST_REGION_ASSISTANT_OTHER_CURRENCY_NOT_NULL, I18nMessage.getLang() == 0 ? destRegion.getTitleZh() : destRegion.getTitleEn());
        }
        if (Objects.isNull(destRegion.getImportCurrency5()) || StringUtils.equals(destRegion.getImportCurrency5(), "0")) {
            throw exception(DEST_REGION_TOTAL_CURRENCY_NOT_NULL, I18nMessage.getLang() == 0 ? destRegion.getTitleZh() : destRegion.getTitleEn());
        }
        return containerNumberOrderSummary(Long.parseLong(destRegion.getImportCurrency1()), Long.parseLong(destRegion.getImportCurrency2()), Long.parseLong(destRegion.getImportCurrency3()),
                Long.parseLong(destRegion.getImportCurrency4()), Long.parseLong(destRegion.getImportCurrency5()), orderIds);
    }


    /**
     * 自编号汇总计算(根据始发地和目的地的配置的换算货币清单，根据相应的实时计算预付与到付的总额)
     *
     * @param collectFreightFeeId        到付运费货币id(目的地)
     * @param collectClearanceFeeId      到付清关费货币id(目的地)
     * @param collectOtherFeeId          到付额外费用货币id(目的地)
     * @param collectAssistantOtherFeeId 到付额外费用副货币id(目的地)
     * @param collectTotalFeeId          总费用货币id(目的地)
     * @param orderIds                   自编号货柜中的订单id列表
     * @return 自编号货柜的订单汇总数据
     */
    private ContainerNumberSummaryDto containerNumberOrderSummary(Long collectFreightFeeId, Long collectClearanceFeeId,
                                                                  Long collectOtherFeeId, Long collectAssistantOtherFeeId,
                                                                  Long collectTotalFeeId, Collection<Long> orderIds) {
        // 获取自编号下订单的全部品名项数据
        List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().in(OrderItemDO::getOrderId, orderIds));
        // 获取自编号下订单的全部应收单数据
        List<ReceivableDO> receivableDOList = receivableService.list(new LambdaQueryWrapper<ReceivableDO>().in(ReceivableDO::getOrderId, orderIds));
        Map<Long, BigDecimal> totalReceivableFreightFeeGroupDtoMap = new HashMap<>(); // 应收运费
        Map<Long, BigDecimal> totalNetReceiptsFreightFeeGroupDtoMap = new HashMap<>(); // 实收运费
        BigDecimal totalReceivableFreightFee = BigDecimal.ZERO; // 应收运费总额(目的地货币换算)
        BigDecimal totalNetReceiptsFreightFee = BigDecimal.ZERO; // 实收运费总额(目的地货币换算)
        Map<Long, BigDecimal> totalNetReceiptsCollectFreightFeeGroupDtoMap = new HashMap<>();// 实收到付运费
        Map<Long, BigDecimal> totalNetReceiptsAdvanceFreightFeeGroupDtoMap = new HashMap<>(); // 实收预付运费
        BigDecimal totalNetReceiptsCollectFreightFee = BigDecimal.ZERO; // 实收到付运费总额
        BigDecimal totalNetReceiptsAdvanceFreightFee = BigDecimal.ZERO; // 实收预付运费总额
        Map<Long, BigDecimal> totalReceivableDiscountFreightFeeGroupDtoMap = new HashMap<>(); // 折扣优惠运费


        Map<Long, BigDecimal> totalReceivableClearanceFeeGroupDtoMap = new HashMap<>(); // 应收清关费
        Map<Long, BigDecimal> totalNetReceiptsClearanceFeeGroupDtoMap = new HashMap<>(); // 实收清关费
        BigDecimal totalReceivableClearanceFee = BigDecimal.ZERO; // 应收清关费总额(目的地货币换算)
        BigDecimal totalNetReceiptsClearanceFee = BigDecimal.ZERO; // 实收清关费总额(目的地货币换算)
        Map<Long, BigDecimal> totalNetReceiptsCollectClearanceFeeGroupDtoMap = new HashMap<>(); // 实收到付清关费
        Map<Long, BigDecimal> totalNetReceiptsAdvanceClearanceFeeGroupDtoMap = new HashMap<>(); // 实收预付清关费
        BigDecimal totalNetReceiptsCollectClearanceFee = BigDecimal.ZERO; // 实收到付清关费总额
        BigDecimal totalNetReceiptsAdvanceClearanceFee = BigDecimal.ZERO; // 实收预付清关费总额
        Map<Long, BigDecimal> totalReceivableDiscountClearanceFeeGroupDtoMap = new HashMap<>(); // 折扣优惠清关费

        Map<Long, BigDecimal> totalReceivableOtherFeeGroupDtoMap = new HashMap<>(); // 应收额外费用
        Map<Long, BigDecimal> totalNetReceiptsOtherFeeGroupDtoMap = new HashMap<>(); // 实收额外费用
        BigDecimal totalReceivableOtherFee = BigDecimal.ZERO; // 应收额外费用总额(目的地货币换算)
        BigDecimal totalNetReceiptsOtherFee = BigDecimal.ZERO; // 实收额外费用总额(目的地货币换算)
        Map<Long, BigDecimal> totalNetReceiptsCollectOtherFeeGroupDtoMap = new HashMap<>(); // 实收到付额外费用
        Map<Long, BigDecimal> totalNetReceiptsAdvanceOtherFeeGroupDtoMap = new HashMap<>(); // 实收预付额外费用
        BigDecimal totalNetReceiptsCollectOtherFee = BigDecimal.ZERO; // 实收到付额外费用总额
        BigDecimal totalNetReceiptsCollectAssistantOtherFee = BigDecimal.ZERO; // 实收到付额外费用副总额
        BigDecimal totalNetReceiptsAdvanceOtherFee = BigDecimal.ZERO; // 实收预付额外费用总额
        BigDecimal totalNetReceiptsAdvanceAssistantOtherFee = BigDecimal.ZERO; // 实收预付额外费用副总额
        Map<Long, BigDecimal> totalDiscountOtherFeeGroupDtoMap = new HashMap<>(); // 折扣优惠额外费用


        Map<Long, BigDecimal> receivableTotalFeeGroupDtoMap = new HashMap<>(); // 应收总费用
        BigDecimal receivableTotalFee = BigDecimal.ZERO; // 应收总费用
        Map<Long, BigDecimal> netReceiptsTotalFeeGroupDtoMap = new HashMap<>(); // 实收总费用
        BigDecimal netReceiptsTotalFee = BigDecimal.ZERO; // 应收总费用
        Map<Long, BigDecimal> discountTotalFeeGroupDtoMap = new HashMap<>(); // 折扣优惠总费用
        BigDecimal discountTotalFee = BigDecimal.ZERO; // 应收总费用
        for (OrderItemDO orderItemDO : orderItemDOList) {
            // 判断品名是否入仓
            boolean isWarehouseIn = Objects.nonNull(orderItemDO.getWarehouseInInfoVO()) && orderItemDO.getWarehouseInInfoVO().getCartonsNum() > 0;
            if (isWarehouseIn) {
                BigDecimal seaFreight = Objects.nonNull(orderItemDO.getSeaFreight()) ? orderItemDO.getSeaFreight().setScale(0, RoundingMode.HALF_UP) : BigDecimal.ZERO;
                BigDecimal receivableSeaFreight = Objects.nonNull(orderItemDO.getReceivableSeaFreight()) ? (orderItemDO.getReceivableSeaFreight().compareTo(BigDecimal.ZERO) == 0 ? seaFreight : orderItemDO.getReceivableSeaFreight()) : BigDecimal.ZERO;
                BigDecimal clearanceFreight = Objects.nonNull(orderItemDO.getClearanceFreight()) ? orderItemDO.getClearanceFreight().setScale(0, RoundingMode.HALF_UP) : BigDecimal.ZERO;
                BigDecimal receivableClearanceFreight = Objects.nonNull(orderItemDO.getReceivableClearanceFreight()) ? (orderItemDO.getReceivableClearanceFreight().compareTo(BigDecimal.ZERO) == 0 ? clearanceFreight : orderItemDO.getReceivableClearanceFreight()) : BigDecimal.ZERO;

                Long freightCurrencyId = Long.parseLong(String.valueOf(orderItemDO.getSeaFreightCurrency()));
                ExchangeRateRespDTO collectFreightRateRespDTO = currencyApi.getCurrencyRate(freightCurrencyId, collectFreightFeeId);
                ExchangeRateRespDTO freightTotalFeeRateRespDTO = currencyApi.getCurrencyRate(freightCurrencyId, collectTotalFeeId);// 运费总费用汇率计算

                // 总应收金额
                if (receivableTotalFeeGroupDtoMap.containsKey(freightCurrencyId)) {
                    receivableTotalFeeGroupDtoMap.put(freightCurrencyId, receivableSeaFreight.add(receivableTotalFeeGroupDtoMap.get(freightCurrencyId)).setScale(0, RoundingMode.HALF_UP));
                } else {
                    receivableTotalFeeGroupDtoMap.put(freightCurrencyId, receivableSeaFreight.setScale(0, RoundingMode.HALF_UP));
                }
                // 总应收转换
                receivableTotalFee = receivableTotalFee.add(receivableSeaFreight.multiply(freightTotalFeeRateRespDTO.getCurrencyRate()));
                // 总实收金额
                if (netReceiptsTotalFeeGroupDtoMap.containsKey(freightCurrencyId)) {
                    netReceiptsTotalFeeGroupDtoMap.put(freightCurrencyId, seaFreight.add(netReceiptsTotalFeeGroupDtoMap.get(freightCurrencyId)).setScale(0, RoundingMode.HALF_UP));
                } else {
                    netReceiptsTotalFeeGroupDtoMap.put(freightCurrencyId, seaFreight.setScale(0, RoundingMode.HALF_UP));
                }
                // 总实收收转换
                netReceiptsTotalFee = netReceiptsTotalFee.add(seaFreight.multiply(freightTotalFeeRateRespDTO.getCurrencyRate()));
                // 总运费应收金额
                if (totalReceivableFreightFeeGroupDtoMap.containsKey(freightCurrencyId)) {
                    totalReceivableFreightFeeGroupDtoMap.put(freightCurrencyId, receivableSeaFreight.add(totalReceivableFreightFeeGroupDtoMap.get(freightCurrencyId)).setScale(0, RoundingMode.HALF_UP));
                } else {
                    totalReceivableFreightFeeGroupDtoMap.put(freightCurrencyId, receivableSeaFreight.setScale(0, RoundingMode.HALF_UP));
                }

                // 总运费实收金额
                if (totalNetReceiptsFreightFeeGroupDtoMap.containsKey(freightCurrencyId)) {
                    totalNetReceiptsFreightFeeGroupDtoMap.put(freightCurrencyId, seaFreight.add(totalNetReceiptsFreightFeeGroupDtoMap.get(freightCurrencyId)).setScale(0, RoundingMode.HALF_UP));
                } else {
                    totalNetReceiptsFreightFeeGroupDtoMap.put(freightCurrencyId, seaFreight.setScale(0, RoundingMode.HALF_UP));
                }
                // 运费的应收与实收根据目的地设置的进口运费货币汇率来转换计算
                totalReceivableFreightFee = totalReceivableFreightFee.add(receivableSeaFreight.multiply(collectFreightRateRespDTO.getCurrencyRate()));
                totalNetReceiptsFreightFee = totalNetReceiptsFreightFee.add(seaFreight.multiply(collectFreightRateRespDTO.getCurrencyRate()));

                if (orderItemDO.getCharging() == 0) {
                    Long clearanceCurrencyId = Long.parseLong(String.valueOf(orderItemDO.getClearanceFreightCurrency()));
                    ExchangeRateRespDTO collectClearanceRateRespDTO = currencyApi.getCurrencyRate(clearanceCurrencyId, collectClearanceFeeId);
                    ExchangeRateRespDTO clearanceTotalFeeRateRespDTO = currencyApi.getCurrencyRate(clearanceCurrencyId, collectTotalFeeId);// 清关费总费汇率计算

                    // 总应收金额
                    if (receivableTotalFeeGroupDtoMap.containsKey(clearanceCurrencyId)) {
                        receivableTotalFeeGroupDtoMap.put(clearanceCurrencyId, receivableClearanceFreight.add(receivableTotalFeeGroupDtoMap.get(clearanceCurrencyId)).setScale(0, RoundingMode.HALF_UP));
                    } else {
                        receivableTotalFeeGroupDtoMap.put(clearanceCurrencyId, receivableClearanceFreight.setScale(0, RoundingMode.HALF_UP));
                    }
                    // 总应收转换
                    receivableTotalFee = receivableTotalFee.add(receivableClearanceFreight.multiply(clearanceTotalFeeRateRespDTO.getCurrencyRate()));
                    // 总实收金额
                    if (netReceiptsTotalFeeGroupDtoMap.containsKey(clearanceCurrencyId)) {
                        netReceiptsTotalFeeGroupDtoMap.put(clearanceCurrencyId, clearanceFreight.add(netReceiptsTotalFeeGroupDtoMap.get(clearanceCurrencyId)).setScale(0, RoundingMode.HALF_UP));
                    } else {
                        netReceiptsTotalFeeGroupDtoMap.put(clearanceCurrencyId, clearanceFreight.setScale(0, RoundingMode.HALF_UP));
                    }
                    // 总实收收转换
                    netReceiptsTotalFee = netReceiptsTotalFee.add(clearanceFreight.multiply(clearanceTotalFeeRateRespDTO.getCurrencyRate()));
                    // 总清关费应收金额
                    if (totalReceivableClearanceFeeGroupDtoMap.containsKey(clearanceCurrencyId)) {
                        totalReceivableClearanceFeeGroupDtoMap.put(clearanceCurrencyId, receivableClearanceFreight.add(totalReceivableClearanceFeeGroupDtoMap.get(clearanceCurrencyId)).setScale(0, RoundingMode.HALF_UP));
                    } else {
                        totalReceivableClearanceFeeGroupDtoMap.put(clearanceCurrencyId, receivableClearanceFreight.setScale(0, RoundingMode.HALF_UP));
                    }
                    // 总清关费实收金额
                    if (totalNetReceiptsClearanceFeeGroupDtoMap.containsKey(clearanceCurrencyId)) {
                        totalNetReceiptsClearanceFeeGroupDtoMap.put(clearanceCurrencyId, clearanceFreight.add(totalNetReceiptsClearanceFeeGroupDtoMap.get(clearanceCurrencyId)).setScale(0, RoundingMode.HALF_UP));
                    } else {
                        totalNetReceiptsClearanceFeeGroupDtoMap.put(clearanceCurrencyId, clearanceFreight.setScale(0, RoundingMode.HALF_UP));
                    }
                    // 清关费的应收与实收转换
                    totalReceivableClearanceFee = totalReceivableClearanceFee.add(receivableClearanceFreight.multiply(collectClearanceRateRespDTO.getCurrencyRate()));
                    totalNetReceiptsClearanceFee = totalNetReceiptsClearanceFee.add(clearanceFreight.multiply(collectClearanceRateRespDTO.getCurrencyRate()));
                }
            }
        }

        for (ReceivableDO receivableDO : receivableDOList) {
            ReceiptDO receiptDO = receiptService.getReceipt(receivableDO.getReceiptId());
            Boolean isChina = null;
            // 收款单不为空，且已核销
            if (Objects.nonNull(receiptDO) && receiptDO.getState() == 4) {
                // TODO 获取当前已核销的收款单核销人所在部门是中国还是目的国
                if (Objects.nonNull(receiptDO.getWriteOffId())) {
                    isChina = adminUserApi.getUserNameIsChina(receiptDO.getWriteOffId());
                }
            }
            Long currencyId = receivableDO.getCurrencyId();
            BigDecimal discountFee = Objects.isNull(receivableDO.getDiscountTotal()) ? BigDecimal.ZERO : receivableDO.getDiscountTotal();
            BigDecimal receivableFee = receivableDO.getTotalAmount();
            BigDecimal netReceiptsFee = receivableDO.getTotalAmount().subtract(discountFee);
            ExchangeRateRespDTO totalFeeRateRespDTO = currencyApi.getCurrencyRate(currencyId, collectTotalFeeId);// 总费默认使用兑美元汇率计算
            if (receivableDO.getFeeSource() == 1 && (receivableDO.getFeeType() == 1 || receivableDO.getFeeType() == 2)) {
                // 如果存在，则运费和清关费的实收需要减去收款单优惠
                // 总实收金额
                if (netReceiptsTotalFeeGroupDtoMap.containsKey(currencyId)) {
                    netReceiptsTotalFeeGroupDtoMap.put(currencyId, netReceiptsTotalFeeGroupDtoMap.get(currencyId).subtract(discountFee).setScale(0, RoundingMode.HALF_UP));
                } else {
                    netReceiptsTotalFeeGroupDtoMap.put(currencyId, discountFee.setScale(0, RoundingMode.HALF_UP).negate());
                }
                netReceiptsTotalFee = netReceiptsTotalFee.subtract(discountFee.multiply(totalFeeRateRespDTO.getCurrencyRate()));
                if (receivableDO.getFeeType() == 1) {
                    ExchangeRateRespDTO collectFreightRateRespDTO = currencyApi.getCurrencyRate(currencyId, collectFreightFeeId);
                    // 总运费实收金额
                    if (totalNetReceiptsFreightFeeGroupDtoMap.containsKey(currencyId)) {
                        totalNetReceiptsFreightFeeGroupDtoMap.put(currencyId, totalNetReceiptsFreightFeeGroupDtoMap.get(currencyId).subtract(discountFee).setScale(0, RoundingMode.HALF_UP));
                    } else {
                        totalNetReceiptsFreightFeeGroupDtoMap.put(currencyId, discountFee.setScale(0, RoundingMode.HALF_UP).negate());
                    }
                    totalNetReceiptsFreightFee = totalNetReceiptsFreightFee.subtract(discountFee.multiply(collectFreightRateRespDTO.getCurrencyRate()));
                    if (receivableDO.getState() == 2 && Objects.nonNull(receiptDO)) {
                        if (Objects.nonNull(isChina) && isChina) {
                            // 中国付
                            // 总预付运费实收金额
                            if (totalNetReceiptsAdvanceFreightFeeGroupDtoMap.containsKey(currencyId)) {
                                totalNetReceiptsAdvanceFreightFeeGroupDtoMap.put(currencyId, netReceiptsFee.add(totalNetReceiptsAdvanceFreightFeeGroupDtoMap.get(currencyId)).setScale(0, RoundingMode.HALF_UP));
                            } else {
                                totalNetReceiptsAdvanceFreightFeeGroupDtoMap.put(currencyId, netReceiptsFee.setScale(0, RoundingMode.HALF_UP));
                            }
                            totalNetReceiptsAdvanceFreightFee = totalNetReceiptsAdvanceFreightFee.add(netReceiptsFee.multiply(collectFreightRateRespDTO.getCurrencyRate()));
                        } else {
                            // 国外付
                            // 总到付运费实收金额
                            if (totalNetReceiptsCollectFreightFeeGroupDtoMap.containsKey(currencyId)) {
                                totalNetReceiptsCollectFreightFeeGroupDtoMap.put(currencyId, netReceiptsFee.add(totalNetReceiptsCollectFreightFeeGroupDtoMap.get(currencyId)).setScale(0, RoundingMode.HALF_UP));
                            } else {
                                totalNetReceiptsCollectFreightFeeGroupDtoMap.put(currencyId, netReceiptsFee.setScale(0, RoundingMode.HALF_UP));
                            }
                            totalNetReceiptsCollectFreightFee = totalNetReceiptsCollectFreightFee.add(netReceiptsFee.multiply(collectFreightRateRespDTO.getCurrencyRate()));
                        }
                    }
                }
                if (receivableDO.getFeeType() == 2) {
                    ExchangeRateRespDTO collectClearanceRateRespDTO = currencyApi.getCurrencyRate(currencyId, collectClearanceFeeId);
                    // 总清关费实收金额
                    if (totalNetReceiptsClearanceFeeGroupDtoMap.containsKey(currencyId)) {
                        totalNetReceiptsClearanceFeeGroupDtoMap.put(currencyId, totalNetReceiptsClearanceFeeGroupDtoMap.get(currencyId).subtract(discountFee).setScale(0, RoundingMode.HALF_UP));
                    } else {
                        totalNetReceiptsClearanceFeeGroupDtoMap.put(currencyId, discountFee.setScale(0, RoundingMode.HALF_UP).negate());
                    }
                    totalNetReceiptsClearanceFee = totalNetReceiptsClearanceFee.subtract(discountFee.multiply(collectClearanceRateRespDTO.getCurrencyRate()));
                    if (receivableDO.getState() == 2) {
                        if (receivableDO.getState() == 2) {
                            if (Objects.nonNull(isChina) && isChina) {
                                // 中国付
                                // 总预付清关费实收金额
                                if (totalNetReceiptsAdvanceClearanceFeeGroupDtoMap.containsKey(currencyId)) {
                                    totalNetReceiptsAdvanceClearanceFeeGroupDtoMap.put(currencyId, netReceiptsFee.add(totalNetReceiptsAdvanceClearanceFeeGroupDtoMap.get(currencyId)).setScale(0, RoundingMode.HALF_UP));
                                } else {
                                    totalNetReceiptsAdvanceClearanceFeeGroupDtoMap.put(currencyId, netReceiptsFee.setScale(0, RoundingMode.HALF_UP));
                                }
                                totalNetReceiptsAdvanceClearanceFee = totalNetReceiptsAdvanceClearanceFee.add(netReceiptsFee.multiply(collectClearanceRateRespDTO.getCurrencyRate()));
                            } else {
                                // 国外付
                                // 总到付清关费实收金额
                                if (totalNetReceiptsCollectClearanceFeeGroupDtoMap.containsKey(currencyId)) {
                                    totalNetReceiptsCollectClearanceFeeGroupDtoMap.put(currencyId, netReceiptsFee.add(totalNetReceiptsCollectClearanceFeeGroupDtoMap.get(currencyId)).setScale(0, RoundingMode.HALF_UP));
                                } else {
                                    totalNetReceiptsCollectClearanceFeeGroupDtoMap.put(currencyId, netReceiptsFee.setScale(0, RoundingMode.HALF_UP));
                                }
                                totalNetReceiptsCollectClearanceFee = totalNetReceiptsCollectClearanceFee.add(netReceiptsFee.multiply(collectClearanceRateRespDTO.getCurrencyRate()));
                            }
                        }
                    }
                }
            } else {
                //额外费用主货币
                ExchangeRateRespDTO collectOtherRateRespDTO = currencyApi.getCurrencyRate(currencyId, collectOtherFeeId);
                // 总应收金额
                if (totalReceivableOtherFeeGroupDtoMap.containsKey(currencyId)) {
                    totalReceivableOtherFeeGroupDtoMap.put(currencyId, receivableFee.add(totalReceivableOtherFeeGroupDtoMap.get(currencyId)).setScale(0, RoundingMode.HALF_UP));
                } else {
                    totalReceivableOtherFeeGroupDtoMap.put(currencyId, receivableFee.setScale(0, RoundingMode.HALF_UP));
                }
                totalReceivableOtherFee = totalReceivableOtherFee.add(receivableFee.multiply(collectOtherRateRespDTO.getCurrencyRate()));
                // 实收额外费用
                if (totalNetReceiptsOtherFeeGroupDtoMap.containsKey(currencyId)) {
                    totalNetReceiptsOtherFeeGroupDtoMap.put(currencyId, netReceiptsFee.add(totalNetReceiptsOtherFeeGroupDtoMap.get(currencyId)).setScale(0, RoundingMode.HALF_UP));
                } else {
                    totalNetReceiptsOtherFeeGroupDtoMap.put(currencyId, netReceiptsFee.setScale(0, RoundingMode.HALF_UP));
                }
                totalNetReceiptsOtherFee = totalNetReceiptsOtherFee.add(netReceiptsFee.multiply(collectOtherRateRespDTO.getCurrencyRate()));
                // 总应收金额
                if (receivableTotalFeeGroupDtoMap.containsKey(currencyId)) {
                    receivableTotalFeeGroupDtoMap.put(currencyId, receivableFee.add(receivableTotalFeeGroupDtoMap.get(currencyId)).setScale(0, RoundingMode.HALF_UP));
                } else {
                    receivableTotalFeeGroupDtoMap.put(currencyId, receivableFee.setScale(0, RoundingMode.HALF_UP));
                }
                receivableTotalFee = receivableTotalFee.add(receivableFee.multiply(totalFeeRateRespDTO.getCurrencyRate()));
                // 总实收金额
                if (netReceiptsTotalFeeGroupDtoMap.containsKey(currencyId)) {
                    netReceiptsTotalFeeGroupDtoMap.put(currencyId, netReceiptsFee.add(netReceiptsTotalFeeGroupDtoMap.get(currencyId)).setScale(0, RoundingMode.HALF_UP));
                } else {
                    netReceiptsTotalFeeGroupDtoMap.put(currencyId, netReceiptsFee.setScale(0, RoundingMode.HALF_UP));
                }
                // 总实收收转换
                netReceiptsTotalFee = netReceiptsTotalFee.add(netReceiptsFee.multiply(totalFeeRateRespDTO.getCurrencyRate()));
                if (receivableDO.getState() == 2) {
                    if (Objects.nonNull(isChina) && isChina) {
                        // 中国付

                        // 实收预付额外费用
                        if (totalNetReceiptsAdvanceOtherFeeGroupDtoMap.containsKey(currencyId)) {
                            totalNetReceiptsAdvanceOtherFeeGroupDtoMap.put(currencyId, netReceiptsFee.add(totalNetReceiptsAdvanceOtherFeeGroupDtoMap.get(currencyId)).setScale(0, RoundingMode.HALF_UP));
                        } else {
                            totalNetReceiptsAdvanceOtherFeeGroupDtoMap.put(currencyId, netReceiptsFee.setScale(0, RoundingMode.HALF_UP));
                        }
                        if (!Objects.equals(currencyId, collectOtherFeeId)) {
                            ExchangeRateRespDTO otherRateRespDTO = currencyApi.getCurrencyRate(currencyId, collectOtherFeeId);
                            totalNetReceiptsAdvanceOtherFee = totalNetReceiptsAdvanceOtherFee.add(netReceiptsFee.multiply(otherRateRespDTO.getCurrencyRate()));
                        } else {
                            totalNetReceiptsAdvanceOtherFee = totalNetReceiptsAdvanceOtherFee.add(netReceiptsFee);
                        }
                        if (!Objects.equals(currencyId, collectAssistantOtherFeeId)) {
                            ExchangeRateRespDTO assistantOtherRateRespDTO = currencyApi.getCurrencyRate(currencyId, collectAssistantOtherFeeId);
                            totalNetReceiptsAdvanceAssistantOtherFee = totalNetReceiptsAdvanceAssistantOtherFee.add(netReceiptsFee.multiply(assistantOtherRateRespDTO.getCurrencyRate()));
                        } else {
                            totalNetReceiptsAdvanceAssistantOtherFee = totalNetReceiptsAdvanceAssistantOtherFee.add(netReceiptsFee);
                        }
                    } else {
                        // 国外付
                        // 实收到付额外费用
                        if (totalNetReceiptsCollectOtherFeeGroupDtoMap.containsKey(currencyId)) {
                            totalNetReceiptsCollectOtherFeeGroupDtoMap.put(currencyId, netReceiptsFee.add(totalNetReceiptsCollectOtherFeeGroupDtoMap.get(currencyId)).setScale(0, RoundingMode.HALF_UP));
                        } else {
                            totalNetReceiptsCollectOtherFeeGroupDtoMap.put(currencyId, netReceiptsFee.setScale(0, RoundingMode.HALF_UP));
                        }
                        if (!Objects.equals(currencyId, collectOtherFeeId)) {
                            ExchangeRateRespDTO otherRateRespDTO = currencyApi.getCurrencyRate(currencyId, collectOtherFeeId);
                            totalNetReceiptsCollectOtherFee = totalNetReceiptsCollectOtherFee.add(netReceiptsFee.multiply(otherRateRespDTO.getCurrencyRate()));
                        } else {
                            totalNetReceiptsCollectOtherFee = totalNetReceiptsCollectOtherFee.add(netReceiptsFee);
                        }
                        if (!Objects.equals(currencyId, collectAssistantOtherFeeId)) {
                            ExchangeRateRespDTO assistantOtherRateRespDTO = currencyApi.getCurrencyRate(currencyId, collectAssistantOtherFeeId);
                            totalNetReceiptsCollectAssistantOtherFee = totalNetReceiptsCollectAssistantOtherFee.add(netReceiptsFee.multiply(assistantOtherRateRespDTO.getCurrencyRate()));
                        } else {
                            totalNetReceiptsCollectAssistantOtherFee = totalNetReceiptsCollectAssistantOtherFee.add(netReceiptsFee);
                        }
                    }
                }
            }
        }

        // 获取所有货币
        Map<Integer, CurrencyRespDTO> currencyRespDTOMap = currencyApi.getAllCurrency();
        if (Objects.isNull(currencyRespDTOMap)) {
            throw exception(NOT_FIND_CURRENCY);
        }

        String totalFreightFeeCurrency = currencyRespDTOMap.get(collectFreightFeeId.intValue()).getTitleEn(); // 总运费货币单位(英文名称)
        String netReceiptsCollectFreightFeeCurrency = currencyRespDTOMap.get(collectFreightFeeId.intValue()).getTitleEn(); // 到付运费货币单位(英文名称)
        String netReceiptsAdvanceFreightFeeCurrency = currencyRespDTOMap.get(collectFreightFeeId.intValue()).getTitleEn(); // 预付运费货币单位(英文名称)
        String totalClearanceFeeCurrency = currencyRespDTOMap.get(collectClearanceFeeId.intValue()).getTitleEn(); // 总清关费货币单位(英文名称)
        String netReceiptsCollectClearanceFeeCurrency = currencyRespDTOMap.get(collectClearanceFeeId.intValue()).getTitleEn(); // 到付清关费货币单位(英文名称)
        String netReceiptsAdvanceClearanceFeeCurrency = currencyRespDTOMap.get(collectClearanceFeeId.intValue()).getTitleEn(); // 预付清关费货币单位(英文名称)
        String totalOtherFeeCurrency = currencyRespDTOMap.get(collectOtherFeeId.intValue()).getTitleEn(); // 总额外费用货币单位(英文名称)
        String netReceiptsCollectOtherFeeCurrency = currencyRespDTOMap.get(collectOtherFeeId.intValue()).getTitleEn(); // 到付额外费用货币单位(英文名称)
        String netReceiptsCollectAssistantOtherFeeCurrency = currencyRespDTOMap.get(collectAssistantOtherFeeId.intValue()).getTitleEn(); // 到付额外费用副货币单位(英文名称)
        String netReceiptsAdvanceOtherFeeCurrency = currencyRespDTOMap.get(collectOtherFeeId.intValue()).getTitleEn(); // 预付额外费用货币单位(英文名称)
        String netReceiptsAdvanceAssistantOtherFeeCurrency = currencyRespDTOMap.get(collectAssistantOtherFeeId.intValue()).getTitleEn(); // 预付额外费用副货币单位(英文名称)
        String totalFeeCurrency = currencyRespDTOMap.get(1).getTitleEn(); // 总应收/实收/折扣费用货币单位(英文名称)--默认美元

        ContainerNumberSummaryDto summaryDto = new ContainerNumberSummaryDto();
        summaryDto.setTotalFreightFeeCurrency(totalFreightFeeCurrency);
        summaryDto.setTotalClearanceFeeCurrency(totalClearanceFeeCurrency);
        summaryDto.setTotalOtherFeeCurrency(totalOtherFeeCurrency);
        summaryDto.setNetReceiptsAdvanceFreightFeeCurrency(netReceiptsAdvanceFreightFeeCurrency);
        summaryDto.setNetReceiptsCollectFreightFeeCurrency(netReceiptsCollectFreightFeeCurrency);
        summaryDto.setNetReceiptsAdvanceClearanceFeeCurrency(netReceiptsAdvanceClearanceFeeCurrency);
        summaryDto.setNetReceiptsCollectClearanceFeeCurrency(netReceiptsCollectClearanceFeeCurrency);
        summaryDto.setNetReceiptsAdvanceOtherFeeCurrency(netReceiptsAdvanceOtherFeeCurrency);
        summaryDto.setNetReceiptsAdvanceAssistantOtherFeeCurrency(netReceiptsAdvanceAssistantOtherFeeCurrency);
        summaryDto.setNetReceiptsCollectOtherFeeCurrency(netReceiptsCollectOtherFeeCurrency);
        summaryDto.setNetReceiptsCollectAssistantOtherFeeCurrency(netReceiptsCollectAssistantOtherFeeCurrency);
        summaryDto.setTotalFeeCurrency(totalFeeCurrency);
        // 总额
        // 订单总金额应收分组
        StringBuilder receivableTotalFeeGroup = new StringBuilder();
        List<FeeGroupDto> receivableTotalFeeGroupDtoList = new ArrayList<>();
        this.

                convertFeeGroup(currencyRespDTOMap, receivableTotalFeeGroupDtoMap, receivableTotalFeeGroupDtoList, receivableTotalFeeGroup);
        summaryDto.setReceivableTotalFeeGroupDtoList(receivableTotalFeeGroupDtoList);
        summaryDto.setReceivableTotalFeeGroup(receivableTotalFeeGroup.toString());
        // 订单总金额实收分组
        StringBuilder netReceiptsTotalFeeGroup = new StringBuilder();
        List<FeeGroupDto> netReceiptsTotalFeeGroupDtoList = new ArrayList<>();
        this.

                convertFeeGroup(currencyRespDTOMap, netReceiptsTotalFeeGroupDtoMap, netReceiptsTotalFeeGroupDtoList, netReceiptsTotalFeeGroup);
        summaryDto.setNetReceiptsTotalFeeGroupDtoList(netReceiptsTotalFeeGroupDtoList);
        summaryDto.setNetReceiptsTotalFeeGroup(netReceiptsTotalFeeGroup.toString());
        // 订单总优惠分组
        StringBuilder discountTotalFeeGroup = new StringBuilder();
        List<FeeGroupDto> discountTotalFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, receivableTotalFeeGroupDtoMap, netReceiptsTotalFeeGroupDtoMap, discountTotalFeeGroupDtoList, discountTotalFeeGroup);
        summaryDto.setDiscountTotalFeeGroupDtoList(discountTotalFeeGroupDtoList);
        summaryDto.setDiscountTotalFeeGroup(discountTotalFeeGroup.toString());
        // 总费用换算成美元设置的货币单位的总应收、总实收、总优惠
        summaryDto.setReceivableTotalFee(receivableTotalFee.setScale(0, RoundingMode.HALF_UP));
        summaryDto.setNetReceiptsTotalFee(netReceiptsTotalFee.setScale(0, RoundingMode.HALF_UP));
        discountTotalFee = receivableTotalFee.subtract(netReceiptsTotalFee);
        summaryDto.setDiscountTotalFee(discountTotalFee.setScale(0, RoundingMode.HALF_UP));

        // 运费
        // 应收运费分组
        StringBuilder receivableFreightFeeGroup = new StringBuilder();
        List<FeeGroupDto> receivableFreightFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalReceivableFreightFeeGroupDtoMap, receivableFreightFeeGroupDtoList, receivableFreightFeeGroup);
        summaryDto.setReceivableFreightFeeGroupDtoList(receivableFreightFeeGroupDtoList);
        summaryDto.setReceivableFreightFeeGroup(receivableFreightFeeGroup.toString());
        // 实收运费分组
        StringBuilder netReceiptsFreightFeeGroup = new StringBuilder();
        List<FeeGroupDto> netReceiptsFreightFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalNetReceiptsFreightFeeGroupDtoMap, netReceiptsFreightFeeGroupDtoList, netReceiptsFreightFeeGroup);
        summaryDto.setNetReceiptsFreightFeeGroupDtoList(netReceiptsFreightFeeGroupDtoList);
        summaryDto.setNetReceiptsFreightFeeGroup(netReceiptsFreightFeeGroup.toString());

        // 实收到付运费分组
        StringBuilder netReceiptsCollectFreightFeeGroup = new StringBuilder();
        List<FeeGroupDto> netReceiptsCollectFreightFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalNetReceiptsCollectFreightFeeGroupDtoMap, netReceiptsCollectFreightFeeGroupDtoList, netReceiptsCollectFreightFeeGroup);
        summaryDto.setNetReceiptsCollectFreightFeeGroupDtoList(netReceiptsCollectFreightFeeGroupDtoList);
        summaryDto.setNetReceiptsCollectFreightFeeGroup(netReceiptsCollectFreightFeeGroup.toString());

        // 实收预付运费分组
        StringBuilder netReceiptsAdvanceFreightFeeGroup = new StringBuilder();
        List<FeeGroupDto> netReceiptsAdvanceFreightFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalNetReceiptsAdvanceFreightFeeGroupDtoMap, netReceiptsAdvanceFreightFeeGroupDtoList, netReceiptsAdvanceFreightFeeGroup);
        summaryDto.setNetReceiptsAdvanceFreightFeeGroupDtoList(netReceiptsAdvanceFreightFeeGroupDtoList);
        summaryDto.setNetReceiptsAdvanceFreightFeeGroup(netReceiptsAdvanceFreightFeeGroup.toString());

        // 运费优惠分组
        StringBuilder discountFreightFeeGroup = new StringBuilder();
        List<FeeGroupDto> discountFreightFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalReceivableFreightFeeGroupDtoMap, totalNetReceiptsFreightFeeGroupDtoMap, discountFreightFeeGroupDtoList, discountFreightFeeGroup);
        summaryDto.setDiscountFreightFeeGroupDtoList(discountFreightFeeGroupDtoList);
        summaryDto.setDiscountFreightFeeGroup(discountFreightFeeGroup.toString());
        // 运费换算成目的地设置的货币单位的总应收、总实收、总优惠
        summaryDto.setTotalReceivableFreightFee(totalReceivableFreightFee.setScale(0, RoundingMode.HALF_UP));
        summaryDto.setTotalNetReceiptsCollectFreightFee(totalNetReceiptsCollectFreightFee.setScale(0, RoundingMode.HALF_UP));
        summaryDto.setTotalNetReceiptsAdvanceFreightFee(totalNetReceiptsAdvanceFreightFee.setScale(0, RoundingMode.HALF_UP));
        summaryDto.setTotalReceivableFreightFee(totalReceivableFreightFee.setScale(0, RoundingMode.HALF_UP));
        summaryDto.setTotalNetReceiptsFreightFee(totalNetReceiptsFreightFee.setScale(0, RoundingMode.HALF_UP));
        summaryDto.setDiscountFreightFee(summaryDto.getTotalReceivableFreightFee().subtract(summaryDto.getTotalNetReceiptsFreightFee()));

        // 清关费
        // 应收清关费分组
        StringBuilder receivableClearanceFeeGroup = new StringBuilder();
        List<FeeGroupDto> receivableClearanceFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalReceivableClearanceFeeGroupDtoMap, receivableClearanceFeeGroupDtoList, receivableClearanceFeeGroup);
        summaryDto.setReceivableClearanceFeeGroupDtoList(receivableClearanceFeeGroupDtoList);
        summaryDto.setReceivableClearanceFeeGroup(receivableClearanceFeeGroup.toString());
        // 实收清关费分组
        StringBuilder netReceiptsClearanceFeeGroup = new StringBuilder();
        List<FeeGroupDto> netReceiptsClearanceFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalNetReceiptsClearanceFeeGroupDtoMap, netReceiptsClearanceFeeGroupDtoList, netReceiptsClearanceFeeGroup);
        summaryDto.setNetReceiptsClearanceFeeGroupDtoList(netReceiptsClearanceFeeGroupDtoList);
        summaryDto.setNetReceiptsClearanceFeeGroup(netReceiptsClearanceFeeGroup.toString());

        // 实收到付清关费分组
        StringBuilder netReceiptsCollectClearanceFeeGroup = new StringBuilder();
        List<FeeGroupDto> netReceiptsCollectClearanceFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalNetReceiptsCollectClearanceFeeGroupDtoMap, netReceiptsCollectClearanceFeeGroupDtoList, netReceiptsCollectClearanceFeeGroup);
        summaryDto.setNetReceiptsCollectClearanceFeeGroupDtoList(netReceiptsCollectClearanceFeeGroupDtoList);
        summaryDto.setNetReceiptsCollectClearanceFeeGroup(netReceiptsCollectClearanceFeeGroup.toString());


        // 实收预付清关费分组
        StringBuilder netReceiptsAdvanceClearanceFeeGroup = new StringBuilder();
        List<FeeGroupDto> netReceiptsAdvanceClearanceFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalNetReceiptsAdvanceClearanceFeeGroupDtoMap, netReceiptsAdvanceClearanceFeeGroupDtoList, netReceiptsAdvanceClearanceFeeGroup);
        summaryDto.setNetReceiptsAdvanceClearanceFeeGroupDtoList(netReceiptsAdvanceClearanceFeeGroupDtoList);
        summaryDto.setNetReceiptsAdvanceClearanceFeeGroup(netReceiptsAdvanceClearanceFeeGroup.toString());

        // 清关费优惠分组
        StringBuilder discountClearanceFeeGroup = new StringBuilder();
        List<FeeGroupDto> discountClearanceFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalReceivableClearanceFeeGroupDtoMap, totalNetReceiptsClearanceFeeGroupDtoMap, discountClearanceFeeGroupDtoList, discountClearanceFeeGroup);
        summaryDto.setDiscountClearanceFeeGroupDtoList(discountClearanceFeeGroupDtoList);
        summaryDto.setDiscountClearanceFeeGroup(discountClearanceFeeGroup.toString());
        // 清关费换算成目的地设置的货币单位的总应收、总实收、总优惠
        summaryDto.setTotalNetReceiptsCollectClearanceFee(totalNetReceiptsCollectClearanceFee.setScale(0, RoundingMode.HALF_UP));
        summaryDto.setTotalNetReceiptsAdvanceClearanceFee(totalNetReceiptsAdvanceClearanceFee.setScale(0, RoundingMode.HALF_UP));
        summaryDto.setTotalReceivableClearanceFee(totalReceivableClearanceFee.setScale(0, RoundingMode.HALF_UP));
        summaryDto.setTotalNetReceiptsClearanceFee(totalNetReceiptsClearanceFee.setScale(0, RoundingMode.HALF_UP));
        summaryDto.setDiscountClearanceFee(totalReceivableClearanceFee.subtract(totalNetReceiptsClearanceFee));
        summaryDto.setDiscountClearanceFee(summaryDto.getTotalReceivableClearanceFee().subtract(summaryDto.getTotalNetReceiptsClearanceFee()));

        // 额外费用
        // 应收额外费用分组
        StringBuilder receivableOtherFeeGroup = new StringBuilder();
        List<FeeGroupDto> receivableOtherFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalReceivableOtherFeeGroupDtoMap, receivableOtherFeeGroupDtoList, receivableOtherFeeGroup);
        summaryDto.setReceivableOtherFeeGroupDtoList(receivableOtherFeeGroupDtoList);
        summaryDto.setReceivableOtherFeeGroup(receivableOtherFeeGroup.toString());
        // 实收额外费用分组
        StringBuilder netReceiptsOtherFeeGroup = new StringBuilder();
        List<FeeGroupDto> netReceiptsOtherFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalNetReceiptsOtherFeeGroupDtoMap, netReceiptsOtherFeeGroupDtoList, netReceiptsOtherFeeGroup);
        summaryDto.setNetReceiptsOtherFeeGroupDtoList(netReceiptsOtherFeeGroupDtoList);
        summaryDto.setNetReceiptsOtherFeeGroup(netReceiptsOtherFeeGroup.toString());

        // 实收到付额外费用分组
        StringBuilder netReceiptsCollectOtherFeeGroup = new StringBuilder();
        List<FeeGroupDto> netReceiptsCollectOtherFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalNetReceiptsCollectOtherFeeGroupDtoMap, netReceiptsCollectOtherFeeGroupDtoList, netReceiptsCollectOtherFeeGroup);
        summaryDto.setNetReceiptsCollectOtherFeeGroupDtoList(netReceiptsCollectOtherFeeGroupDtoList);
        summaryDto.setNetReceiptsCollectOtherFeeGroup(netReceiptsCollectOtherFeeGroup.toString());

        // 实收预付额外费用分组
        StringBuilder netReceiptsAdvanceOtherFeeGroup = new StringBuilder();
        List<FeeGroupDto> netReceiptsAdvanceOtherFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalNetReceiptsAdvanceOtherFeeGroupDtoMap, netReceiptsAdvanceOtherFeeGroupDtoList, netReceiptsAdvanceOtherFeeGroup);
        summaryDto.setNetReceiptsAdvanceOtherFeeGroupDtoList(netReceiptsAdvanceOtherFeeGroupDtoList);
        summaryDto.setNetReceiptsAdvanceOtherFeeGroup(netReceiptsAdvanceOtherFeeGroup.toString());

        // 额外费用优惠分组
        StringBuilder discountOtherFeeGroup = new StringBuilder();
        List<FeeGroupDto> discountOtherFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalReceivableOtherFeeGroupDtoMap, totalNetReceiptsOtherFeeGroupDtoMap, discountOtherFeeGroupDtoList, discountOtherFeeGroup);
        summaryDto.setDiscountOtherFeeGroupDtoList(discountOtherFeeGroupDtoList);
        summaryDto.setDiscountOtherFeeGroup(discountOtherFeeGroup.toString());
        // 额外费用换算成目的地设置的货币单位的总应收、总实收、总优惠
        summaryDto.setTotalNetReceiptsCollectOtherFee(totalNetReceiptsCollectOtherFee.setScale(0, RoundingMode.HALF_UP));
        summaryDto.setTotalNetReceiptsCollectAssistantOtherFee(totalNetReceiptsCollectAssistantOtherFee.setScale(0, RoundingMode.HALF_UP));
        summaryDto.setTotalNetReceiptsAdvanceOtherFee(totalNetReceiptsAdvanceOtherFee.setScale(0, RoundingMode.HALF_UP));
        summaryDto.setTotalNetReceiptsAdvanceAssistantOtherFee(totalNetReceiptsAdvanceAssistantOtherFee.setScale(0, RoundingMode.HALF_UP));
        summaryDto.setTotalReceivableOtherFee(totalReceivableOtherFee.setScale(0, RoundingMode.HALF_UP));
        summaryDto.setTotalNetReceiptsOtherFee(totalNetReceiptsOtherFee.setScale(0, RoundingMode.HALF_UP));
        summaryDto.setDiscountOtherFee(summaryDto.getTotalReceivableOtherFee().subtract(summaryDto.getTotalNetReceiptsOtherFee()));
        return summaryDto;
    }

    @Override
    public OrderCostSummaryDto orderSummaryByOrderId(Long orderId) {
        OrderBackInfoDto dto = this.info(orderId);
        if (Objects.isNull(dto)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        return getOrderCostSummaryDto(dto, null);
    }

    @Override
    public OrderCostSummaryDto getOrderCostSummaryDto(OrderBackInfoDto orderBackInfoDto, OrderBackPageVO orderBackPageVO) {
        if (Objects.isNull(orderBackInfoDto) && Objects.isNull(orderBackPageVO)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        // 获取所有货币
        Map<Integer, CurrencyRespDTO> currencyRespDTOMap = currencyApi.getAllCurrency();
        if (Objects.isNull(currencyRespDTOMap)) {
            throw exception(NOT_FIND_CURRENCY);
        }
        OrderCostSummaryDto summaryDto = new OrderCostSummaryDto();
        if (Objects.nonNull(orderBackInfoDto)) {
            BeanUtils.copyProperties(orderBackInfoDto, summaryDto);
            summaryDto.setWeightUnit(orderBackInfoDto.getUseWeightUnit());
            summaryDto.setVolumeUnit(orderBackInfoDto.getUseVolumeUnit());
        } else {
            BeanUtils.copyProperties(orderBackPageVO, summaryDto);
        }
        List<OrderItemBackVO> orderItemBackVOList = orderItemMapper.infoItemList(summaryDto.getOrderId(), I18nMessage.getLang());
        // 获取到订单的全部应收单数据
        List<ReceivableDO> receivableDOList = receivableService.allByOrderId(summaryDto.getOrderId());
        // TODO 收费数据计算需要考虑订单是否入仓的区别
        Set<Long> seaFreightCurrencyIds = orderItemBackVOList.stream().filter(vo -> vo.getSeaFreightCurrency() > 0).map(OrderItemBackVO::getSeaFreightCurrency).map(c -> Long.parseLong(String.valueOf(c))).collect(Collectors.toSet());
        Set<Long> clearanceFreightCurrencyIds = orderItemBackVOList.stream().filter(vo -> vo.getCharging() == 0 && vo.getClearanceFreightCurrency() > 0).map(OrderItemBackVO::getClearanceFreightCurrency).map(c -> Long.parseLong(String.valueOf(c))).collect(Collectors.toSet());
        Set<Long> allCurrencyIds = new HashSet<>();
        Set<Long> otherCurrencyIds = new HashSet<>();
        if (CollectionUtil.isNotEmpty(orderItemBackVOList)) {
            otherCurrencyIds = receivableDOList.stream().filter(rb -> (rb.getFeeSource() != 1) || (rb.getFeeType() != 1 && rb.getFeeType() != 2)).map(ReceivableDO::getCurrencyId).collect(Collectors.toSet());
            allCurrencyIds.addAll(receivableDOList.stream().map(ReceivableDO::getCurrencyId).collect(Collectors.toSet()));
        }
        allCurrencyIds.addAll(seaFreightCurrencyIds);
        allCurrencyIds.addAll(clearanceFreightCurrencyIds);
        if (allCurrencyIds.size() == 0) {
            throw exception(NOT_FIND_CURRENCY);
        }
        List<ExchangeRateRespDTO> exchangeRateRespDTOList = currencyApi.getCurrencyRateList(allCurrencyIds, 1L);
        Map<Long, ExchangeRateRespDTO> exchangeRateRespDTOMap = exchangeRateRespDTOList.stream().collect(Collectors.toMap(ExchangeRateRespDTO::getSourceCurrencyId, (v -> v), (v1, v2) -> v2));
        // 实际收费数据
        BigDecimal orgChargeVolume = BigDecimal.ZERO;
        BigDecimal orgChargeWeight = BigDecimal.ZERO;
        BigDecimal orgChargeQuantity = BigDecimal.ZERO;
        BigDecimal chargeVolume = BigDecimal.ZERO;
        BigDecimal chargeWeight = BigDecimal.ZERO;
        BigDecimal chargeQuantity = BigDecimal.ZERO;
        BigDecimal totalWorth = BigDecimal.ZERO; // 总货值

        BigDecimal totalReceivableFreightFee = BigDecimal.ZERO; // 应收总运费
        BigDecimal totalNetReceiptsFreightFee = BigDecimal.ZERO;// 实收总运费
        BigDecimal totalDiscountFreightFee = BigDecimal.ZERO;// 运费优惠总额
        Map<Long, BigDecimal> totalReceivableFreightFeeGroupDtoMap = new HashMap<>();
        Map<Long, BigDecimal> totalNetReceiptsFreightFeeGroupDtoMap = new HashMap<>();
        Map<Long, BigDecimal> writeOffFreightFeeGroupDtoMap = new HashMap<>();
        Map<Long, BigDecimal> notWriteOffFreightFeeGroupDtoMap = new HashMap<>();
        long seaFreightCurrencyId = 1L;// 默认

        BigDecimal totalReceivableClearanceFee = BigDecimal.ZERO; // 应收总清关费
        BigDecimal totalNetReceiptsClearanceFee = BigDecimal.ZERO;// 实收总清关费
        BigDecimal totalDiscountClearanceFee = BigDecimal.ZERO;// 清关费费优惠总额
        Map<Long, BigDecimal> totalReceivableClearanceFeeGroupDtoMap = new HashMap<>();
        Map<Long, BigDecimal> totalNetReceiptsClearanceFeeGroupDtoMap = new HashMap<>();
        Map<Long, BigDecimal> writeOffClearanceFeeGroupDtoMap = new HashMap<>();
        Map<Long, BigDecimal> notWriteOffClearanceFeeGroupDtoMap = new HashMap<>();
        long clearanceFeeCurrencyId = 1L;// 默认

        BigDecimal totalReceivableOtherFee = BigDecimal.ZERO; // 应收额外总费用
        BigDecimal totalNetReceiptsOtherFee = BigDecimal.ZERO;// 实收额外总费用
        Map<Long, BigDecimal> totalReceivableOtherFeeGroupDtoMap = new HashMap<>();
        Map<Long, BigDecimal> totalNetReceiptsOtherFeeGroupDtoMap = new HashMap<>();
        Map<Long, BigDecimal> totalDiscountOtherFeeGroupDtoMap = new HashMap<>();
        Map<Long, BigDecimal> writeOffOtherFeeGroupDtoMap = new HashMap<>();
        Map<Long, BigDecimal> notWriteOffOtherFeeGroupDtoMap = new HashMap<>();
        long otherFeeCurrencyId = 1L;// 默认

        BigDecimal receivableTotalAmount = BigDecimal.ZERO;// 应收总金额
        BigDecimal netReceiptsTotalAmount = BigDecimal.ZERO;// 实收总金额
        BigDecimal writeOffAmount = BigDecimal.ZERO; // 总核销金额
        Map<Long, BigDecimal> receivableTotalFeeGroupDtoMap = new HashMap<>();
        Map<Long, BigDecimal> netReceiptsTotalFeeGroupDtoMap = new HashMap<>();
        Map<Long, BigDecimal> writeOffTotalFeeGroupDtoMap = new HashMap<>();
        Map<Long, BigDecimal> notWriteOffTotalFeeGroupDtoMap = new HashMap<>();
        long writeOffAmountCurrencyId = 1L;// 默认

        // 优惠
        for (OrderItemBackVO orderItemBackVO : orderItemBackVOList) {
            // 判断品名是否入仓
            boolean isWarehouseIn = Objects.nonNull(orderItemBackVO.getWarehouseInInfoVO()) && orderItemBackVO.getWarehouseInInfoVO().getCartonsNum() > 0;
            ExchangeRateRespDTO freightExchangeRateRespDTO = exchangeRateRespDTOMap.get(Long.valueOf(String.valueOf(orderItemBackVO.getSeaFreightCurrency())));
            ExchangeRateRespDTO clearanceExchangeRateRespDTO = exchangeRateRespDTOMap.get(Long.valueOf(String.valueOf(orderItemBackVO.getClearanceFreightCurrency())));
            if (Objects.isNull(freightExchangeRateRespDTO)) {
                freightExchangeRateRespDTO = new ExchangeRateRespDTO();
                freightExchangeRateRespDTO.setSourceCurrencyId(1L);
                freightExchangeRateRespDTO.setSourceCurrencyCode("$");
                freightExchangeRateRespDTO.setTargetCurrencyId(1L);
                freightExchangeRateRespDTO.setTargetCurrencyCode("$");
                freightExchangeRateRespDTO.setCurrencyRate(new BigDecimal("1"));//美元兑美元，默认1:1
            }
            if (Objects.isNull(clearanceExchangeRateRespDTO)) {
                clearanceExchangeRateRespDTO = new ExchangeRateRespDTO();
                clearanceExchangeRateRespDTO.setSourceCurrencyId(1L);
                clearanceExchangeRateRespDTO.setSourceCurrencyCode("$");
                clearanceExchangeRateRespDTO.setTargetCurrencyId(1L);
                clearanceExchangeRateRespDTO.setTargetCurrencyCode("$");
                clearanceExchangeRateRespDTO.setCurrencyRate(new BigDecimal("1"));//美元兑美元，默认1:1
            }
            chargeVolume = chargeVolume.add(orderItemBackVO.getChargeVolume().compareTo(orderItemBackVO.getMinMeteringVolume()) < 0 ?
                    orderItemBackVO.getMinMeteringVolume() : orderItemBackVO.getChargeVolume());
            chargeWeight = chargeWeight.add(orderItemBackVO.getChargeWeight().compareTo(orderItemBackVO.getMinMeteringWeight()) < 0 ?
                    orderItemBackVO.getMinMeteringWeight() : orderItemBackVO.getChargeWeight());
            chargeQuantity = chargeQuantity.add(orderItemBackVO.getChargeQuantity().compareTo(orderItemBackVO.getMinMeteringQuantity()) < 0 ?
                    orderItemBackVO.getMinMeteringQuantity() : orderItemBackVO.getChargeQuantity());
            orgChargeVolume = orgChargeVolume.add(orderItemBackVO.getOrgChargeVolume());
            orgChargeWeight = orgChargeWeight.add(orderItemBackVO.getOrgChargeWeight());
            orgChargeQuantity = orgChargeQuantity.add(orderItemBackVO.getOrgChargeQuantity());
            totalWorth = totalWorth.add(orderItemBackVO.getWorth());
            // TODO 应收运费费总额
            // TODO 应收清关费总额
            // TODO 应收订单总额 这里只会累加订单计价产生的运费与清关费，额外费用这里不累加，如果需要累加需要在应收单中去累加
            BigDecimal seaFreight = orderItemBackVO.getSeaFreight() == null ? BigDecimal.ZERO : orderItemBackVO.getSeaFreight().setScale(0, RoundingMode.HALF_UP);
            BigDecimal receivableSeaFreight;
            if (orderItemBackVO.getReceivableSeaFreight() == null || orderItemBackVO.getReceivableSeaFreight().compareTo(BigDecimal.ZERO) == 0) {
                receivableSeaFreight = seaFreight;
            } else {
                receivableSeaFreight = orderItemBackVO.getReceivableSeaFreight();
            }
            //BigDecimal receivableSeaFreight = orderItemBackVO.getReceivableSeaFreight().compareTo(BigDecimal.ZERO) == 0 ? seaFreight : orderItemBackVO.getReceivableSeaFreight();
            BigDecimal clearanceFreight = orderItemBackVO.getClearanceFreight() == null ? BigDecimal.ZERO : orderItemBackVO.getClearanceFreight().setScale(0, RoundingMode.HALF_UP);
            BigDecimal receivableClearanceFreight;
            if (orderItemBackVO.getReceivableClearanceFreight() == null || orderItemBackVO.getReceivableClearanceFreight().compareTo(BigDecimal.ZERO) == 0) {
                receivableClearanceFreight = clearanceFreight;
            } else {
                receivableClearanceFreight = orderItemBackVO.getReceivableClearanceFreight();
            }
            //BigDecimal receivableClearanceFreight = orderItemBackVO.getReceivableClearanceFreight().compareTo(BigDecimal.ZERO) == 0 ? clearanceFreight : orderItemBackVO.getReceivableClearanceFreight();
            if (allCurrencyIds.size() > 1) {
                // 当所有费用的货币不统一时，总的优惠金额需要统一转换成美元来累加处理
                // 该订单下清关费多种货币，需要统一转换成美元来累加处理
                BigDecimal freightReceivableFee = receivableSeaFreight.multiply(freightExchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP);
                BigDecimal freightNetReceiptsFee = seaFreight.multiply(freightExchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP);
                BigDecimal clearanceReceivableFee = receivableClearanceFreight.multiply(clearanceExchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP);
                BigDecimal clearanceNetReceiptsFee = clearanceFreight.multiply(clearanceExchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP);
                receivableTotalAmount = receivableTotalAmount.add(freightReceivableFee).add(clearanceReceivableFee);
                netReceiptsTotalAmount = netReceiptsTotalAmount.add(freightNetReceiptsFee).add(clearanceNetReceiptsFee);
            } else {
                receivableTotalAmount = receivableTotalAmount.add(receivableSeaFreight).add(receivableClearanceFreight);
                netReceiptsTotalAmount = netReceiptsTotalAmount.add(seaFreight).add(clearanceFreight);
                writeOffAmountCurrencyId = allCurrencyIds.stream().findFirst().orElse(1L);
            }
            if (isWarehouseIn) {
                Long freightCurrencyId = Long.parseLong(String.valueOf(orderItemBackVO.getSeaFreightCurrency()));
                Long clearanceCurrencyId = Long.parseLong(String.valueOf(orderItemBackVO.getClearanceFreightCurrency()));
                // 总应收金额
                if (receivableTotalFeeGroupDtoMap.containsKey(freightCurrencyId)) {
                    receivableTotalFeeGroupDtoMap.put(freightCurrencyId, receivableSeaFreight.add(receivableTotalFeeGroupDtoMap.get(freightCurrencyId)).setScale(0, RoundingMode.HALF_UP));
                } else {
                    receivableTotalFeeGroupDtoMap.put(freightCurrencyId, receivableSeaFreight.setScale(0, RoundingMode.HALF_UP));
                }
                // 总实收金额
                if (netReceiptsTotalFeeGroupDtoMap.containsKey(freightCurrencyId)) {
                    netReceiptsTotalFeeGroupDtoMap.put(freightCurrencyId, seaFreight.add(netReceiptsTotalFeeGroupDtoMap.get(freightCurrencyId)).setScale(0, RoundingMode.HALF_UP));
                } else {
                    netReceiptsTotalFeeGroupDtoMap.put(freightCurrencyId, seaFreight.setScale(0, RoundingMode.HALF_UP));
                }
                // 总运费应收金额
                if (totalReceivableFreightFeeGroupDtoMap.containsKey(freightCurrencyId)) {
                    totalReceivableFreightFeeGroupDtoMap.put(freightCurrencyId, receivableSeaFreight.add(totalReceivableFreightFeeGroupDtoMap.get(freightCurrencyId)).setScale(0, RoundingMode.HALF_UP));
                } else {
                    totalReceivableFreightFeeGroupDtoMap.put(freightCurrencyId, receivableSeaFreight.setScale(0, RoundingMode.HALF_UP));
                }
                // 总运费实收金额
                if (totalNetReceiptsFreightFeeGroupDtoMap.containsKey(freightCurrencyId)) {
                    totalNetReceiptsFreightFeeGroupDtoMap.put(freightCurrencyId, seaFreight.add(totalNetReceiptsFreightFeeGroupDtoMap.get(freightCurrencyId)).setScale(0, RoundingMode.HALF_UP));
                } else {
                    totalNetReceiptsFreightFeeGroupDtoMap.put(freightCurrencyId, seaFreight.setScale(0, RoundingMode.HALF_UP));
                }

                // 总应收金额
                if (receivableTotalFeeGroupDtoMap.containsKey(clearanceCurrencyId)) {
                    receivableTotalFeeGroupDtoMap.put(clearanceCurrencyId, receivableClearanceFreight.add(receivableTotalFeeGroupDtoMap.get(clearanceCurrencyId)).setScale(0, RoundingMode.HALF_UP));
                } else {
                    receivableTotalFeeGroupDtoMap.put(clearanceCurrencyId, receivableClearanceFreight.setScale(0, RoundingMode.HALF_UP));
                }
                // 总实收金额
                if (netReceiptsTotalFeeGroupDtoMap.containsKey(clearanceCurrencyId)) {
                    netReceiptsTotalFeeGroupDtoMap.put(clearanceCurrencyId, clearanceFreight.add(netReceiptsTotalFeeGroupDtoMap.get(clearanceCurrencyId)).setScale(0, RoundingMode.HALF_UP));
                } else {
                    netReceiptsTotalFeeGroupDtoMap.put(clearanceCurrencyId, clearanceFreight.setScale(0, RoundingMode.HALF_UP));
                }
                // 总清关费应收金额
                if (totalReceivableClearanceFeeGroupDtoMap.containsKey(clearanceCurrencyId)) {
                    totalReceivableClearanceFeeGroupDtoMap.put(clearanceCurrencyId, receivableClearanceFreight.add(totalReceivableClearanceFeeGroupDtoMap.get(clearanceCurrencyId)).setScale(0, RoundingMode.HALF_UP));
                } else {
                    totalReceivableClearanceFeeGroupDtoMap.put(clearanceCurrencyId, receivableClearanceFreight.setScale(0, RoundingMode.HALF_UP));
                }
                // 总清关费实收金额
                if (totalNetReceiptsClearanceFeeGroupDtoMap.containsKey(clearanceCurrencyId)) {
                    totalNetReceiptsClearanceFeeGroupDtoMap.put(clearanceCurrencyId, clearanceFreight.add(totalNetReceiptsClearanceFeeGroupDtoMap.get(clearanceCurrencyId)).setScale(0, RoundingMode.HALF_UP));
                } else {
                    totalNetReceiptsClearanceFeeGroupDtoMap.put(clearanceCurrencyId, clearanceFreight.setScale(0, RoundingMode.HALF_UP));
                }
            }
            // 运费优惠
            if (seaFreightCurrencyIds.size() > 1) {
                // 该订单下运费多种货币，需要统一转换成美元来累加处理
                if (isWarehouseIn) {
                    // 入仓的品名才计算实收
                    BigDecimal receivableFee = orderItemBackVO.getReceivableSeaFreight().multiply(clearanceExchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP);
                    totalReceivableFreightFee = totalReceivableFreightFee.add(receivableFee).setScale(0, RoundingMode.HALF_UP);
                    BigDecimal fee = orderItemBackVO.getSeaFreight().multiply(clearanceExchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP);
                    totalNetReceiptsFreightFee = totalNetReceiptsFreightFee.add(fee);
                    BigDecimal discountFee = orderItemBackVO.getDiscountFreightTotalPrice().multiply(freightExchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP);
                    totalDiscountFreightFee = totalDiscountFreightFee.add(discountFee).setScale(0, RoundingMode.HALF_UP);
                }

            } else {
                // 该订单下运费单一货币，不需要转换汇率，直接累加
                if (isWarehouseIn) {
                    // 入仓的品名才计算实收
                    totalReceivableFreightFee = totalReceivableFreightFee.add(orderItemBackVO.getReceivableSeaFreight());
                    totalNetReceiptsFreightFee = totalNetReceiptsFreightFee.add(orderItemBackVO.getSeaFreight());
                    seaFreightCurrencyId = seaFreightCurrencyIds.stream().findFirst().orElse(1L);
                    totalDiscountFreightFee = totalDiscountFreightFee.add(orderItemBackVO.getDiscountFreightTotalPrice());
                }
            }
            // 清关费优惠
            if (clearanceFreightCurrencyIds.size() > 1) {
                // 该订单下清关费多种货币，需要统一转换成美元来累加处理
                if (isWarehouseIn) {
                    // 入仓的品名才计算实收
                    BigDecimal receivableFee = orderItemBackVO.getReceivableClearanceFreight().multiply(clearanceExchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP);
                    totalReceivableClearanceFee = totalReceivableClearanceFee.add(receivableFee).setScale(0, RoundingMode.HALF_UP);
                    BigDecimal fee = orderItemBackVO.getClearanceFreight().multiply(clearanceExchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP);
                    totalNetReceiptsClearanceFee = totalNetReceiptsClearanceFee.add(fee).setScale(0, RoundingMode.HALF_UP);
                    BigDecimal discountFee = orderItemBackVO.getDiscountClearanceFeeTotalPrice().multiply(clearanceExchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP);
                    totalDiscountClearanceFee = totalDiscountClearanceFee.add(discountFee).setScale(0, RoundingMode.HALF_UP);
                }
            } else {
                // 该订单下清关费单一货币，不需要转换汇率，直接累加
                if (isWarehouseIn) {
                    // 入仓的品名才计算实收
                    totalReceivableClearanceFee = totalReceivableClearanceFee.add(orderItemBackVO.getReceivableClearanceFreight()).setScale(0, RoundingMode.HALF_UP);
                    totalNetReceiptsClearanceFee = totalNetReceiptsClearanceFee.add(orderItemBackVO.getClearanceFreight()).setScale(0, RoundingMode.HALF_UP);
                    clearanceFeeCurrencyId = clearanceFreightCurrencyIds.stream().findFirst().orElse(1L);
                    totalDiscountClearanceFee = totalDiscountClearanceFee.add(orderItemBackVO.getDiscountClearanceFeeTotalPrice()).setScale(0, RoundingMode.HALF_UP);
                }
            }

        }
        for (ReceivableDO receivableDO : receivableDOList) {
            Long currencyId = receivableDO.getCurrencyId();
            BigDecimal writeOffProportion = StringUtils.isNotBlank(receivableDO.getWriteOffProportion()) ?
                    new BigDecimal(receivableDO.getWriteOffProportion()).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP) : BigDecimal.ZERO;
            BigDecimal discountFee = Objects.isNull(receivableDO.getDiscountTotal()) ? BigDecimal.ZERO : receivableDO.getDiscountTotal();
            BigDecimal receivableFee = receivableDO.getTotalAmount();
            BigDecimal netReceiptsFee = receivableDO.getTotalAmount().subtract(discountFee);
            // 财务2.2-新增的核销金额
            BigDecimal writeOffAmountActual = receivableDO.getWriteOffAmount() == null ? BigDecimal.ZERO : receivableDO.getWriteOffAmount();
            BigDecimal notWriteOffAmount = BigDecimal.ZERO;
            if (receivableDO.getState() != 2 || netReceiptsFee.compareTo(writeOffAmountActual) > 0) {
                notWriteOffAmount = netReceiptsFee.subtract(writeOffAmountActual);
            }
            // 财务2.2-修改
            if (writeOffTotalFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                writeOffTotalFeeGroupDtoMap.put(receivableDO.getCurrencyId(), writeOffAmountActual.add(writeOffTotalFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
            } else {
                writeOffTotalFeeGroupDtoMap.put(receivableDO.getCurrencyId(), writeOffAmountActual);
            }
            // 计算未收
            if (notWriteOffAmount.compareTo(BigDecimal.ZERO) >= 0) {
                if (notWriteOffTotalFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                    notWriteOffTotalFeeGroupDtoMap.put(receivableDO.getCurrencyId(), notWriteOffAmount.add(notWriteOffTotalFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                } else {
                    notWriteOffTotalFeeGroupDtoMap.put(receivableDO.getCurrencyId(), notWriteOffAmount);
                }
            }
            //if (receivableDO.getState() == 1) {
            //    // 核销中总金额
            //    BigDecimal fee = netReceiptsFee.multiply(writeOffProportion);
            //    if (writeOffTotalFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
            //        writeOffTotalFeeGroupDtoMap.put(receivableDO.getCurrencyId(), fee.add(writeOffTotalFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
            //    } else {
            //        writeOffTotalFeeGroupDtoMap.put(receivableDO.getCurrencyId(), fee);
            //    }
            //} else if (receivableDO.getState() == 2) {
            //    // 已核销总金额
            //    if (writeOffTotalFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
            //        writeOffTotalFeeGroupDtoMap.put(receivableDO.getCurrencyId(), netReceiptsFee.add(writeOffTotalFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
            //    } else {
            //        writeOffTotalFeeGroupDtoMap.put(receivableDO.getCurrencyId(), netReceiptsFee);
            //    }
            //}
            // 应收单实收金额 = 应收单总额 - 收款优惠金额
            ExchangeRateRespDTO exchangeRateRespDTO = exchangeRateRespDTOMap.get(receivableDO.getCurrencyId());
            if (Objects.isNull(exchangeRateRespDTO)) {
                exchangeRateRespDTO = new ExchangeRateRespDTO();
                exchangeRateRespDTO.setSourceCurrencyId(1L);
                exchangeRateRespDTO.setSourceCurrencyCode("$");
                exchangeRateRespDTO.setTargetCurrencyId(1L);
                exchangeRateRespDTO.setTargetCurrencyCode("$");
                exchangeRateRespDTO.setCurrencyRate(new BigDecimal("1"));//美元兑美元，默认1:1
            }
            if (allCurrencyIds.size() > 1) {

                // 该订单下运费多种货币，需要统一转换成美元来累加处理
                BigDecimal fee = netReceiptsFee.multiply(exchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP);
                if (receivableDO.getState() == 1) {
                    // 核销中的金额计算
                    writeOffAmount = writeOffAmount.add(fee.multiply(writeOffProportion));
                } else if (receivableDO.getState() == 2) {
                    // 已核销应收单的实收金额即是已核销金额
                    writeOffAmount = writeOffAmount.add(fee);
                }
                // 所有费用的货币id不统一，则计算所有费用的数据时
                if (receivableDO.getFeeSource() == 1 && (receivableDO.getFeeType() == 1 || receivableDO.getFeeType() == 2)) {
                    // 运费和清关费的应收只需要将总实收减去收款单可能的优惠
                    netReceiptsTotalAmount = netReceiptsTotalAmount.subtract(discountFee.multiply(exchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP));
                } else {
                    // 额外费用的应收需要累加到总应收和实收中
                    receivableTotalAmount = receivableTotalAmount.add(receivableFee.multiply(exchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP));
                    netReceiptsTotalAmount = netReceiptsTotalAmount.add(netReceiptsFee.multiply(exchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP));
                }
            } else {
                // 该订单下费用单一货币，不需要转换汇率，直接累加
                if (receivableDO.getState() == 1) {
                    // TODO 核销中的金额计算
                    BigDecimal fee = netReceiptsFee.multiply(writeOffProportion);
                    writeOffAmount = writeOffAmount.add(fee);
                } else if (receivableDO.getState() == 2) {
                    // 已核销应收单的实收金额即是已核销金额
                    writeOffAmount = writeOffAmount.add(netReceiptsFee);
                }
                // 所有费用的货币id不统一，则计算所有费用的数据时
                if (receivableDO.getFeeSource() == 1 && (receivableDO.getFeeType() == 1 || receivableDO.getFeeType() == 2)) {
                    // 运费和清关费的应收只需要将总实收减去收款单可能的优惠
                    netReceiptsTotalAmount = netReceiptsTotalAmount.subtract(discountFee);
                } else {
                    // 额外费用的应收需要累加到总应收和实收中
                    receivableTotalAmount = receivableTotalAmount.add(receivableFee);
                    netReceiptsTotalAmount = netReceiptsTotalAmount.add(netReceiptsFee);
                }
            }
            if (receivableDO.getFeeSource() == 1 && (receivableDO.getFeeType() == 1 || receivableDO.getFeeType() == 2)) {
                // 总实收金额
                if (netReceiptsTotalFeeGroupDtoMap.containsKey(currencyId)) {
                    netReceiptsTotalFeeGroupDtoMap.put(currencyId, netReceiptsTotalFeeGroupDtoMap.get(currencyId).subtract(discountFee).setScale(0, RoundingMode.HALF_UP));
                } else {
                    netReceiptsTotalFeeGroupDtoMap.put(currencyId, discountFee.setScale(0, RoundingMode.HALF_UP).negate());
                }
                // 计算费用
                if (receivableDO.getFeeType() == 1) {
                    // 总运费实收金额
                    if (totalNetReceiptsFreightFeeGroupDtoMap.containsKey(currencyId)) {
                        totalNetReceiptsFreightFeeGroupDtoMap.put(currencyId, totalNetReceiptsFreightFeeGroupDtoMap.get(currencyId).subtract(discountFee).setScale(0, RoundingMode.HALF_UP));
                    } else {
                        totalNetReceiptsFreightFeeGroupDtoMap.put(currencyId, discountFee.setScale(0, RoundingMode.HALF_UP).negate());
                    }
                    if (writeOffFreightFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                        writeOffFreightFeeGroupDtoMap.put(receivableDO.getCurrencyId(), writeOffAmountActual.add(writeOffFreightFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                    } else {
                        writeOffFreightFeeGroupDtoMap.put(receivableDO.getCurrencyId(), writeOffAmountActual);
                    }
                    // 计算未收
                    if (notWriteOffAmount.compareTo(BigDecimal.ZERO) >= 0) {
                        if (notWriteOffFreightFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                            notWriteOffFreightFeeGroupDtoMap.put(receivableDO.getCurrencyId(), notWriteOffAmount.add(notWriteOffFreightFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                        } else {
                            notWriteOffFreightFeeGroupDtoMap.put(receivableDO.getCurrencyId(), notWriteOffAmount);
                        }
                    }
                    //if (receivableDO.getState() == 1) {
                    //    // 核销中的金额计算
                    //    BigDecimal fee = netReceiptsFee.multiply(writeOffProportion);
                    //    // 收款单运费已核销金额
                    //    if (writeOffFreightFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                    //        writeOffFreightFeeGroupDtoMap.put(receivableDO.getCurrencyId(), fee.add(writeOffFreightFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                    //    } else {
                    //        writeOffFreightFeeGroupDtoMap.put(receivableDO.getCurrencyId(), fee);
                    //    }
                    //} else if (receivableDO.getState() == 2) {
                    //    // 收款单运费已核销金额
                    //    if (writeOffFreightFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                    //        writeOffFreightFeeGroupDtoMap.put(receivableDO.getCurrencyId(), netReceiptsFee.add(writeOffFreightFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                    //    } else {
                    //        writeOffFreightFeeGroupDtoMap.put(receivableDO.getCurrencyId(), netReceiptsFee);
                    //    }
                    //}
                    if (seaFreightCurrencyIds.size() > 1) {
                        // 该订单下运费多种货币，需要统一转换成美元来累加处理,实收运费减去收款单的优惠金额
                        totalNetReceiptsFreightFee = totalNetReceiptsFreightFee.subtract(discountFee.multiply(exchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP));
                    } else {
                        // 该订单下运费单一货币，不需要转换汇率，实收运费减去收款单的优惠金额
                        totalNetReceiptsFreightFee = totalNetReceiptsFreightFee.subtract(discountFee);
                    }
                }
                if (receivableDO.getFeeType() == 2) {
                    // 总清关费实收金额计算，减去收款单优惠金额
                    if (totalNetReceiptsClearanceFeeGroupDtoMap.containsKey(currencyId)) {
                        totalNetReceiptsClearanceFeeGroupDtoMap.put(currencyId, totalNetReceiptsClearanceFeeGroupDtoMap.get(currencyId).subtract(discountFee).setScale(0, RoundingMode.HALF_UP));
                    } else {
                        totalNetReceiptsClearanceFeeGroupDtoMap.put(currencyId, discountFee.setScale(0, RoundingMode.HALF_UP).negate());
                    }
                    if (writeOffClearanceFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                        writeOffClearanceFeeGroupDtoMap.put(receivableDO.getCurrencyId(), writeOffAmountActual.add(writeOffClearanceFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                    } else {
                        writeOffClearanceFeeGroupDtoMap.put(receivableDO.getCurrencyId(), writeOffAmountActual);
                    }
                    // 计算未收
                    if (notWriteOffAmount.compareTo(BigDecimal.ZERO) >= 0) {
                        if (notWriteOffClearanceFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                            notWriteOffClearanceFeeGroupDtoMap.put(receivableDO.getCurrencyId(), notWriteOffAmount.add(notWriteOffClearanceFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                        } else {
                            notWriteOffClearanceFeeGroupDtoMap.put(receivableDO.getCurrencyId(), notWriteOffAmount);
                        }
                    }
                    //if (receivableDO.getState() == 1) {
                    //    // 核销中的金额计算
                    //    BigDecimal fee = netReceiptsFee.multiply(writeOffProportion);
                    //    if (writeOffClearanceFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                    //        writeOffClearanceFeeGroupDtoMap.put(receivableDO.getCurrencyId(), fee.add(writeOffClearanceFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                    //    } else {
                    //        writeOffClearanceFeeGroupDtoMap.put(receivableDO.getCurrencyId(), fee);
                    //    }
                    //} else if (receivableDO.getState() == 2) {
                    //    // 收款单清关费已核销金额
                    //    if (writeOffClearanceFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                    //        writeOffClearanceFeeGroupDtoMap.put(receivableDO.getCurrencyId(), netReceiptsFee.add(writeOffClearanceFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                    //    } else {
                    //        writeOffClearanceFeeGroupDtoMap.put(receivableDO.getCurrencyId(), netReceiptsFee);
                    //    }
                    //}
                    // 清关费实收
                    if (clearanceFreightCurrencyIds.size() > 1) {
                        // 该订单下清关多种货币，需要统一转换成美元来累加处理，实收金额直接减去收款单优惠
                        totalNetReceiptsClearanceFee = totalNetReceiptsClearanceFee.subtract(discountFee.multiply(exchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP));
                    } else {
                        // 该订单下清关费单一货币，不需要转换汇率，实收金额直接减去收款单优惠
                        totalNetReceiptsClearanceFee = totalNetReceiptsClearanceFee.subtract(discountFee);
                    }
                }
            } else {
                // 收款单额外优惠金额
                if (totalDiscountOtherFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                    totalDiscountOtherFeeGroupDtoMap.put(receivableDO.getCurrencyId(), discountFee.add(totalDiscountOtherFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                } else {
                    totalDiscountOtherFeeGroupDtoMap.put(receivableDO.getCurrencyId(), discountFee);
                }
                // 收款单额外应收金额
                if (totalReceivableOtherFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                    totalReceivableOtherFeeGroupDtoMap.put(receivableDO.getCurrencyId(), receivableFee.add(totalReceivableOtherFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                } else {
                    totalReceivableOtherFeeGroupDtoMap.put(receivableDO.getCurrencyId(), receivableFee);
                }
                // 收款单额外实收金额
                if (totalNetReceiptsOtherFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                    totalNetReceiptsOtherFeeGroupDtoMap.put(receivableDO.getCurrencyId(), netReceiptsFee.add(totalNetReceiptsOtherFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                } else {
                    totalNetReceiptsOtherFeeGroupDtoMap.put(receivableDO.getCurrencyId(), netReceiptsFee);
                }
                if (writeOffOtherFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                    writeOffOtherFeeGroupDtoMap.put(receivableDO.getCurrencyId(), writeOffAmountActual.add(writeOffOtherFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                } else {
                    writeOffOtherFeeGroupDtoMap.put(receivableDO.getCurrencyId(), writeOffAmountActual);
                }
                // 计算未收
                if (notWriteOffAmount.compareTo(BigDecimal.ZERO) >= 0) {
                    if (notWriteOffOtherFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                        notWriteOffOtherFeeGroupDtoMap.put(receivableDO.getCurrencyId(), notWriteOffAmount.add(notWriteOffOtherFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                    } else {
                        notWriteOffOtherFeeGroupDtoMap.put(receivableDO.getCurrencyId(), notWriteOffAmount);
                    }
                }
                //if (receivableDO.getState() == 1) {
                //    // 核销中的金额计算
                //    BigDecimal fee = netReceiptsFee.multiply(writeOffProportion);
                //    // 额外已核销金额
                //    if (writeOffOtherFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                //        writeOffOtherFeeGroupDtoMap.put(receivableDO.getCurrencyId(), fee.add(writeOffOtherFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                //    } else {
                //        writeOffOtherFeeGroupDtoMap.put(receivableDO.getCurrencyId(), fee);
                //    }
                //} else if (receivableDO.getState() == 2) {
                //    // 额外已核销金额
                //    if (writeOffOtherFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                //        writeOffOtherFeeGroupDtoMap.put(receivableDO.getCurrencyId(), netReceiptsFee.add(writeOffOtherFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                //    } else {
                //        writeOffOtherFeeGroupDtoMap.put(receivableDO.getCurrencyId(), netReceiptsFee);
                //    }
                //}
                // 收款单总应收金额
                if (receivableTotalFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                    receivableTotalFeeGroupDtoMap.put(receivableDO.getCurrencyId(), receivableDO.getTotalAmount().add(receivableTotalFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                } else {
                    receivableTotalFeeGroupDtoMap.put(receivableDO.getCurrencyId(), receivableDO.getTotalAmount());
                }
                // 收款单总实收金额
                if (netReceiptsTotalFeeGroupDtoMap.containsKey(receivableDO.getCurrencyId())) {
                    netReceiptsTotalFeeGroupDtoMap.put(receivableDO.getCurrencyId(), receivableDO.getTotalAmount().add(netReceiptsTotalFeeGroupDtoMap.get(receivableDO.getCurrencyId())));
                } else {
                    netReceiptsTotalFeeGroupDtoMap.put(receivableDO.getCurrencyId(), receivableDO.getTotalAmount());
                }
                // TODO 额外费用的实收金额是否需要累加，这里的实收额外费用是不减收款单优惠的金额
                if (otherCurrencyIds.size() > 1) {
                    // 该订单下其他费用多种货币，需要统一转换成美元来累加处理
                    totalReceivableOtherFee = totalReceivableOtherFee.add(receivableFee.multiply(exchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP));
                    BigDecimal fee = netReceiptsFee.multiply(exchangeRateRespDTO.getCurrencyRate()).setScale(0, RoundingMode.HALF_UP);
                    totalNetReceiptsOtherFee = totalNetReceiptsOtherFee.add(fee);
                } else {
                    // 该订单下其他费用单一货币，不需要转换汇率，直接累加
                    otherFeeCurrencyId = otherCurrencyIds.stream().findFirst().orElse(1L);
                    totalReceivableOtherFee = totalReceivableOtherFee.add(receivableFee);
                    totalNetReceiptsOtherFee = totalNetReceiptsOtherFee.add(netReceiptsFee);
                }

            }
        }
        summaryDto.setTotalWorth(totalWorth.setScale(0, RoundingMode.HALF_UP));


        // 运费
        // 应收运费分组
        StringBuilder receivableFreightFeeGroup = new StringBuilder();
        List<FeeGroupDto> receivableFreightFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalReceivableFreightFeeGroupDtoMap, receivableFreightFeeGroupDtoList, receivableFreightFeeGroup);
        summaryDto.setReceivableFreightFeeGroupDtoList(receivableFreightFeeGroupDtoList);
        summaryDto.setReceivableFreightFeeGroup(receivableFreightFeeGroup.toString());
        // 实收运费分组
        StringBuilder netReceiptsFreightFeeGroup = new StringBuilder();
        List<FeeGroupDto> netReceiptsFreightFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalNetReceiptsFreightFeeGroupDtoMap, netReceiptsFreightFeeGroupDtoList, netReceiptsFreightFeeGroup);
        summaryDto.setNetReceiptsFreightFeeGroupDtoList(netReceiptsFreightFeeGroupDtoList);
        summaryDto.setNetReceiptsFreightFeeGroup(netReceiptsFreightFeeGroup.toString());

        // 运费优惠分组
        StringBuilder discountFreightFeeGroup = new StringBuilder();
        List<FeeGroupDto> discountFreightFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalReceivableFreightFeeGroupDtoMap, totalNetReceiptsFreightFeeGroupDtoMap, discountFreightFeeGroupDtoList, discountFreightFeeGroup);
        summaryDto.setDiscountFreightFeeGroupDtoList(discountFreightFeeGroupDtoList);
        summaryDto.setDiscountFreightFeeGroup(discountFreightFeeGroup.toString());
        // 已收运费分组
        StringBuilder writeOffFreightFeeGroup = new StringBuilder();
        List<FeeGroupDto> writeOffFreightFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, writeOffFreightFeeGroupDtoMap, writeOffFreightFeeGroupDtoList, writeOffFreightFeeGroup);
        summaryDto.setWriteOffFreightFeeGroupDtoList(writeOffFreightFeeGroupDtoList);
        summaryDto.setWriteOffFreightFeeGroup(writeOffFreightFeeGroup.toString());
        // 未收运费分组
        StringBuilder notWriteOffFreightFeeGroup = new StringBuilder();
        List<FeeGroupDto> notWriteOffFreightFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, notWriteOffFreightFeeGroupDtoMap, notWriteOffFreightFeeGroupDtoList, notWriteOffFreightFeeGroup);
        summaryDto.setNotWriteOffFreightFeeGroupDtoList(notWriteOffFreightFeeGroupDtoList);
        summaryDto.setNotWriteOffFreightFeeGroup(notWriteOffFreightFeeGroup.toString());

        // 当应收金额为0时，赋予应收金额等于实收金额，拆单子拆单历史数据会有此类情况
        totalNetReceiptsFreightFee = totalNetReceiptsFreightFee.setScale(0, RoundingMode.HALF_UP);
        totalReceivableFreightFee = totalReceivableFreightFee.compareTo(BigDecimal.ZERO) == 0 ? totalNetReceiptsFreightFee : totalReceivableFreightFee.setScale(0, RoundingMode.HALF_UP);
        summaryDto.setReceivableFreightFee(totalReceivableFreightFee);
        summaryDto.setNetReceiptsFreightFee(totalNetReceiptsFreightFee);// TODO 实收是否减去可能的收款单优惠，也可能没生成应收单就没有优惠，当前实收是品名的成交单价*收费数据得出
        summaryDto.setDiscountFreightTotalPrice(summaryDto.getReceivableFreightFee().subtract(summaryDto.getNetReceiptsFreightFee()));
        summaryDto.setSeaFreightCurrency((int) seaFreightCurrencyId);
        //清关费
        // 应收清关费分组
        StringBuilder receivableClearanceFeeGroup = new StringBuilder();
        List<FeeGroupDto> receivableClearanceFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalReceivableClearanceFeeGroupDtoMap, receivableClearanceFeeGroupDtoList, receivableClearanceFeeGroup);
        summaryDto.setReceivableClearanceFeeGroupDtoList(receivableClearanceFeeGroupDtoList);
        summaryDto.setReceivableClearanceFeeGroup(receivableClearanceFeeGroup.toString());
        // 实收清关费分组
        StringBuilder netReceiptsClearanceFeeGroup = new StringBuilder();
        List<FeeGroupDto> netReceiptsClearanceFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalNetReceiptsClearanceFeeGroupDtoMap, netReceiptsClearanceFeeGroupDtoList, netReceiptsClearanceFeeGroup);
        summaryDto.setNetReceiptsClearanceFeeGroupDtoList(netReceiptsClearanceFeeGroupDtoList);
        summaryDto.setNetReceiptsClearanceFeeGroup(netReceiptsClearanceFeeGroup.toString());

        // 清关费优惠分组
        StringBuilder discountClearanceFeeGroup = new StringBuilder();
        List<FeeGroupDto> discountClearanceFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalReceivableClearanceFeeGroupDtoMap, totalNetReceiptsClearanceFeeGroupDtoMap, discountClearanceFeeGroupDtoList, discountClearanceFeeGroup);
        summaryDto.setDiscountClearanceFeeGroupDtoList(discountClearanceFeeGroupDtoList);
        summaryDto.setDiscountClearanceFeeGroup(discountClearanceFeeGroup.toString());
        // 已收清关费分组
        StringBuilder writeOffClearanceFeeGroup = new StringBuilder();
        List<FeeGroupDto> writeOffClearanceFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, writeOffClearanceFeeGroupDtoMap, writeOffClearanceFeeGroupDtoList, writeOffClearanceFeeGroup);
        summaryDto.setWriteOffClearanceFeeGroupDtoList(writeOffClearanceFeeGroupDtoList);
        summaryDto.setWriteOffClearanceFeeGroup(writeOffClearanceFeeGroup.toString());
        // 未收清关费分组
        StringBuilder notWriteOffClearanceFeeGroup = new StringBuilder();
        List<FeeGroupDto> notWriteOffClearanceFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, notWriteOffClearanceFeeGroupDtoMap, notWriteOffClearanceFeeGroupDtoList, notWriteOffClearanceFeeGroup);
        summaryDto.setNotWriteOffClearanceFeeGroupDtoList(notWriteOffClearanceFeeGroupDtoList);
        summaryDto.setNotWriteOffClearanceFeeGroup(notWriteOffClearanceFeeGroup.toString());

        totalNetReceiptsClearanceFee = totalNetReceiptsClearanceFee.setScale(0, RoundingMode.HALF_UP);
        totalReceivableClearanceFee = totalReceivableClearanceFee.compareTo(BigDecimal.ZERO) == 0 ? totalNetReceiptsClearanceFee : totalReceivableClearanceFee.setScale(0, RoundingMode.HALF_UP);
        summaryDto.setReceivableClearanceFee(totalReceivableClearanceFee);
        summaryDto.setNetReceiptsClearanceFee(totalNetReceiptsClearanceFee); // TODO 实收是否减去可能的收款单优惠，也可能没生成应收单就没有优惠，当前实收是品名的成交单价*收费数据得出
        summaryDto.setDiscountClearanceFee(summaryDto.getReceivableClearanceFee().subtract(summaryDto.getNetReceiptsClearanceFee()));
        summaryDto.setClearanceFreightCurrency((int) clearanceFeeCurrencyId);
        // 额外费用
        // 应收额外费用分组
        StringBuilder receivableOtherFeeGroup = new StringBuilder();
        List<FeeGroupDto> receivableOtherFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalReceivableOtherFeeGroupDtoMap, receivableOtherFeeGroupDtoList, receivableOtherFeeGroup);
        summaryDto.setReceivableOtherFeeGroupDtoList(receivableOtherFeeGroupDtoList);
        summaryDto.setReceivableOtherFeeGroup(receivableOtherFeeGroup.toString());
        // 实收额外费用分组
        StringBuilder netReceiptsOtherFeeGroup = new StringBuilder();
        List<FeeGroupDto> netReceiptsOtherFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalNetReceiptsOtherFeeGroupDtoMap, netReceiptsOtherFeeGroupDtoList, netReceiptsOtherFeeGroup);
        summaryDto.setNetReceiptsOtherFeeGroupDtoList(netReceiptsOtherFeeGroupDtoList);
        summaryDto.setNetReceiptsOtherFeeGroup(netReceiptsOtherFeeGroup.toString());

        // 额外费用优惠分组
        StringBuilder discountOtherFeeGroup = new StringBuilder();
        List<FeeGroupDto> discountOtherFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, totalReceivableOtherFeeGroupDtoMap, totalNetReceiptsOtherFeeGroupDtoMap, discountOtherFeeGroupDtoList, discountOtherFeeGroup);
        summaryDto.setDiscountOtherFeeGroupDtoList(discountOtherFeeGroupDtoList);
        summaryDto.setDiscountOtherFeeGroup(discountOtherFeeGroup.toString());
        // 已收额外费用分组
        StringBuilder writeOffOtherFeeGroup = new StringBuilder();
        List<FeeGroupDto> writeOffOtherFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, writeOffOtherFeeGroupDtoMap, writeOffOtherFeeGroupDtoList, writeOffOtherFeeGroup);
        summaryDto.setWriteOffOtherFeeGroupDtoList(writeOffOtherFeeGroupDtoList);
        summaryDto.setWriteOffOtherFeeGroup(writeOffOtherFeeGroup.toString());
        // 未收额外费用分组
        StringBuilder notWriteOffOtherFeeGroup = new StringBuilder();
        List<FeeGroupDto> notWriteOffOtherFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, notWriteOffOtherFeeGroupDtoMap, notWriteOffOtherFeeGroupDtoList, notWriteOffOtherFeeGroup);
        summaryDto.setNotWriteOffOtherFeeGroupDtoList(notWriteOffOtherFeeGroupDtoList);
        summaryDto.setNotWriteOffOtherFeeGroup(notWriteOffOtherFeeGroup.toString());

        totalReceivableOtherFee = totalReceivableOtherFee.setScale(0, RoundingMode.HALF_UP);
        totalNetReceiptsOtherFee = totalNetReceiptsOtherFee.setScale(0, RoundingMode.HALF_UP);
        summaryDto.setReceivableOtherFee(totalReceivableOtherFee);
        summaryDto.setNetReceiptsOtherFee(totalNetReceiptsOtherFee);
        summaryDto.setDiscountOtherFee(totalReceivableOtherFee.subtract(totalNetReceiptsOtherFee));
        summaryDto.setOtherFeeCurrency((int) otherFeeCurrencyId);

        // TODO 当应收金额为0时，赋予应收金额等于实收金额，拆单子拆单历史数据会有此类情况
        netReceiptsTotalAmount = netReceiptsTotalAmount.setScale(0, RoundingMode.HALF_UP);
        receivableTotalAmount = receivableTotalAmount.compareTo(BigDecimal.ZERO) == 0 ? netReceiptsTotalAmount : receivableTotalAmount.setScale(0, RoundingMode.HALF_UP);
        summaryDto.setReceivableTotalAmount(receivableTotalAmount);
        summaryDto.setNetReceiptsTotalAmount(netReceiptsTotalAmount);
        // 订单总金额应收分组
        StringBuilder receivableTotalFeeGroup = new StringBuilder();
        List<FeeGroupDto> receivableTotalFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, receivableTotalFeeGroupDtoMap, receivableTotalFeeGroupDtoList, receivableTotalFeeGroup);
        summaryDto.setReceivableTotalFeeGroupDtoList(receivableTotalFeeGroupDtoList);
        summaryDto.setReceivableTotalFeeGroup(receivableTotalFeeGroup.toString());
        // 订单总金额实收分组
        StringBuilder netReceiptsTotalFeeGroup = new StringBuilder();
        List<FeeGroupDto> netReceiptsTotalFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, netReceiptsTotalFeeGroupDtoMap, netReceiptsTotalFeeGroupDtoList, netReceiptsTotalFeeGroup);
        summaryDto.setNetReceiptsTotalFeeGroupDtoList(netReceiptsTotalFeeGroupDtoList);
        summaryDto.setNetReceiptsTotalFeeGroup(netReceiptsTotalFeeGroup.toString());
        // 订单优惠分组
        StringBuilder discountTotalFeeGroup = new StringBuilder();
        List<FeeGroupDto> discountTotalFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, receivableTotalFeeGroupDtoMap, netReceiptsTotalFeeGroupDtoMap, discountTotalFeeGroupDtoList, discountTotalFeeGroup);
        summaryDto.setDiscountTotalFeeGroupDtoList(discountTotalFeeGroupDtoList);
        summaryDto.setDiscountTotalFeeGroup(discountTotalFeeGroup.toString());
        // 已收订单总额分组
        StringBuilder writeOffTotalFeeGroup = new StringBuilder();
        List<FeeGroupDto> writeOffTotalFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, writeOffTotalFeeGroupDtoMap, writeOffTotalFeeGroupDtoList, writeOffTotalFeeGroup);
        summaryDto.setWriteOffTotalFeeGroupDtoList(writeOffTotalFeeGroupDtoList);
        summaryDto.setWriteOffTotalFeeGroup(writeOffTotalFeeGroup.toString());
        // 未收订单总额分组
        StringBuilder notWriteOffTotalFeeGroup = new StringBuilder();
        List<FeeGroupDto> notWriteOffTotalFeeGroupDtoList = new ArrayList<>();
        this.convertFeeGroup(currencyRespDTOMap, notWriteOffTotalFeeGroupDtoMap, notWriteOffTotalFeeGroupDtoList, notWriteOffTotalFeeGroup);
        summaryDto.setNotWriteOffTotalFeeGroupDtoList(notWriteOffTotalFeeGroupDtoList);
        summaryDto.setNotWriteOffTotalFeeGroup(notWriteOffTotalFeeGroup.toString());

        // 应收总额 - 实收总额 = 总优惠金额
        summaryDto.setDiscountTotalAmount(summaryDto.getReceivableTotalAmount().subtract(summaryDto.getNetReceiptsTotalAmount()));
        summaryDto.setWriteOffAmount(writeOffAmount.setScale(0, RoundingMode.HALF_UP));
        summaryDto.setWriteOffCurrencyId(writeOffAmountCurrencyId);
        // TODO 自这里实收金额为0时计算会报错，做容错处理，但是编号下的订单实收金额为0的数据是有问题的，待确认原因
        // 计算订单核销比例， 订单已核销金额/订单实收总额, 应为显示应该为百分比数值，所以需要乘以100取整数
        if (Objects.nonNull(summaryDto.getNetReceiptsTotalAmount()) && summaryDto.getNetReceiptsTotalAmount().compareTo(BigDecimal.ZERO) > 0) {
            summaryDto.setWriteOffProportion(summaryDto.getWriteOffAmount().divide(summaryDto.getNetReceiptsTotalAmount(), 6, RoundingMode.HALF_UP)
                    .multiply(new BigDecimal("100")).setScale(4, RoundingMode.HALF_UP));
        } else {
            summaryDto.setWriteOffProportion(BigDecimal.ZERO.setScale(0, RoundingMode.HALF_UP));
        }
        // 将百分比转换为整数百分符号字符串
        summaryDto.setWriteOffRatio(summaryDto.getWriteOffProportion().toString() + "%");


        summaryDto.setOrgChargeNum(summaryDto.getSumNum());
        summaryDto.setOrgChargeQuantity(orgChargeQuantity);
        summaryDto.setOrgChargeWeight(orgChargeWeight);
        summaryDto.setOrgChargeVolume(orgChargeVolume);

        summaryDto.setRealityChargeNum(summaryDto.getSumNum());
        summaryDto.setRealityChargeQuantity(chargeQuantity);
        summaryDto.setRealityChargeWeight(chargeWeight);
        summaryDto.setRealityChargeVolume(chargeVolume);

        summaryDto.setWarehouseInData(summaryDto.getSumNum() + "箱/" + summaryDto.getSumVolume() + "m³/" + summaryDto.getSumWeight() + "Kg");
        summaryDto.setChargeData(summaryDto.getSumNum() + "箱/" + chargeVolume + "m³/" + chargeWeight + "Kg");
        return summaryDto;
    }

    private void convertFeeGroup(Map<Integer, CurrencyRespDTO> currencyRespDTOMap, Map<Long, BigDecimal> feeGroupDtoMap, List<FeeGroupDto> feeGroupDtoList, StringBuilder sb) {
        for (Map.Entry<Long, BigDecimal> entry : feeGroupDtoMap.entrySet()) {
            int currencyId = entry.getKey().intValue();
            if (currencyRespDTOMap.get(currencyId) == null) {
                continue;
            }
            FeeGroupDto feeGroupDto = new FeeGroupDto();
            CurrencyRespDTO currencyRespDTO = currencyRespDTOMap.get(currencyId);
            feeGroupDto.setCurrencyId(entry.getKey());
            feeGroupDto.setAmount(entry.getValue().setScale(0, RoundingMode.HALF_UP));
            if (Objects.nonNull(currencyRespDTO)) {
                feeGroupDto.setCurrencyName(currencyRespDTO.getTitleEn());
            } else {
                feeGroupDto.setCurrencyName("?");
            }
            if (StringUtils.isNotBlank(sb)) {
                sb.append(StrUtil.COMMA);
            }
            sb.append(feeGroupDto.getAmount().toString()).append(feeGroupDto.getCurrencyName());
            feeGroupDtoList.add(feeGroupDto);
        }
    }

    private void convertFeeGroup(Map<Integer, CurrencyRespDTO> currencyRespDTOMap, Map<Long, BigDecimal> feeGroupDtoMap1, Map<Long, BigDecimal> feeGroupDtoMap2, List<FeeGroupDto> feeGroupDtoList, StringBuilder sb) {
        for (Map.Entry<Long, BigDecimal> entry : feeGroupDtoMap1.entrySet()) {
            int currencyId = entry.getKey().intValue();
            if (currencyRespDTOMap.get(currencyId) == null) {
                continue;
            }
            FeeGroupDto feeGroupDto = new FeeGroupDto();
            CurrencyRespDTO currencyRespDTO = currencyRespDTOMap.get(entry.getKey().intValue());
            feeGroupDto.setCurrencyId(entry.getKey());
            BigDecimal amount2 = feeGroupDtoMap2.get(entry.getKey());
            feeGroupDto.setAmount(entry.getValue().subtract(Objects.isNull(amount2) ? BigDecimal.ZERO : amount2).setScale(0, RoundingMode.HALF_UP));
            if (Objects.nonNull(currencyRespDTO)) {
                feeGroupDto.setCurrencyName(currencyRespDTO.getTitleEn());
            } else {
                feeGroupDto.setCurrencyName("?");
            }
            if (StringUtils.isNotBlank(sb)) {
                sb.append(StrUtil.COMMA);
            }
            sb.append(feeGroupDto.getAmount().toString()).append(feeGroupDto.getCurrencyName());
            feeGroupDtoList.add(feeGroupDto);
        }
    }

    @Override
    public OrderDetailSummaryDto orderDetailSummaryByOrderId(Long orderId) {
        OrderDetailSummaryDto detailSummaryDto = new OrderDetailSummaryDto();
        OrderDO orderDO = orderMapper.selectById(orderId);
        // TODO 保费信息获取
        OrderInsuranceFeeDto orderInsuranceFeeDto = new OrderInsuranceFeeDto();
        BigDecimal totalWorth = BigDecimal.ZERO;//总货值
        BigDecimal insuranceFee = new BigDecimal("2");//保费
        Integer insuranceCurrency = 1;//保费货币默认美元
        if (StringUtils.isNotBlank(orderDO.getCost())) {
            CostVO costVO = JSONObject.parseObject(orderDO.getCost(), CostVO.class);
            totalWorth = costVO.getTotalWorth();
            insuranceFee = costVO.getInsuranceFee();
            insuranceCurrency = Objects.nonNull(costVO.getInsuranceCurrencyId()) ? Math.toIntExact(costVO.getInsuranceCurrencyId()) : 1;
        }
        orderInsuranceFeeDto.setTotalWorth(totalWorth);
        orderInsuranceFeeDto.setWorthCurrency(3);//默认货值以RMB来计量
        orderInsuranceFeeDto.setReceivableInsuranceFee(insuranceFee);
        orderInsuranceFeeDto.setInsuranceCurrency(insuranceCurrency);//保费货币id

        List<OrderItemBackVO> orderItemBackVOList = orderItemMapper.infoItemList(orderId, I18nMessage.getLang());

        // 获取到订单的全部应收单数据
        List<ReceivableDO> receivableDOList = receivableService.receivableListByOrderId(orderId);
        Map<Long, ReceivableDO> freightReceivableDOMap = new HashMap<>();
        Map<Long, ReceivableDO> clearanceReceivableDOMap = new HashMap<>();
        // 应收费用列表汇总
        // 对应收列表进行分组 保价费、特需费用、费用申请、订单应收单运费、订单应收单清关费
        if (CollectionUtil.isNotEmpty(receivableDOList)) {
            // 订单应收单运费
            freightReceivableDOMap = receivableDOList.stream().filter(rb -> rb.getFeeSource() == 1 && rb.getFeeType() == 1).collect(Collectors.toMap(ReceivableDO::getOrderItemId, v -> v, (v1, v2) -> v2));
            // 订单应收单清关费
            clearanceReceivableDOMap = receivableDOList.stream().filter(rb -> rb.getFeeSource() == 1 && rb.getFeeType() == 2).collect(Collectors.toMap(ReceivableDO::getOrderItemId, v -> v, (v1, v2) -> v2));

            // 特需费用
            List<OrderReceivableFeeDto> specialNeedFeeList = receivableDOList.stream().filter(rb -> rb.getFeeSource() == 3)
                    .map(getFeeDtoFunction()).collect(Collectors.toList());
            detailSummaryDto.setSpecialNeedFeeList(specialNeedFeeList);
            // 费用申请
            List<OrderReceivableFeeDto> feeApplicationList = receivableDOList.stream().filter(rb -> rb.getFeeSource() == 2)
                    .map(getFeeDtoFunction()).collect(Collectors.toList());
            detailSummaryDto.setFeeApplicationList(feeApplicationList);

            // 应收单保费
            ReceivableDO receivableDO = receivableDOList.stream().filter(rb -> rb.getFeeSource() == 1 && rb.getFeeType() == 6).findFirst().orElse(null);
            if (Objects.nonNull(receivableDO)) {
                orderInsuranceFeeDto.setDiscountInsuranceFee(Objects.isNull(receivableDO.getDiscountTotal()) ? BigDecimal.ZERO : receivableDO.getDiscountTotal());
                // 当优惠金额不为空并且大于0时，重新计算实收金额，否则实收金额就等于应收金额
                if (Objects.nonNull(receivableDO.getDiscountTotal()) && receivableDO.getDiscountTotal().compareTo(BigDecimal.ZERO) > 0) {
                    orderInsuranceFeeDto.setRealityInsuranceFee(receivableDO.getTotalAmount().subtract(receivableDO.getDiscountTotal()));
                } else {
                    orderInsuranceFeeDto.setRealityInsuranceFee(receivableDO.getTotalAmount());
                }
            }
        }
        detailSummaryDto.setInsuranceFeeDto(orderInsuranceFeeDto);
        if (CollectionUtil.isNotEmpty(orderItemBackVOList)) {
            // 订单项费用汇总
            List<OrderItemCostDto> orderItemCostDtoList = new ArrayList<>();
            List<CouponInfoVO> couponInfoVOList = new ArrayList<>();
            for (OrderItemBackVO it : orderItemBackVOList) {
                WarehouseInInfoVO warehouseInInfoVO = it.getWarehouseInInfoVO();
                if (StringUtils.isNotBlank(it.getCouponInfo())) {
                    List<CouponInfoVO> itemCouponInfoVOList = JSONObject.parseArray(it.getCouponInfo(), CouponInfoVO.class);
                    if (CollectionUtil.isNotEmpty(itemCouponInfoVOList)) {
                        couponInfoVOList.addAll(itemCouponInfoVOList);
                    }
                }
                OrderItemCostDto orderItemCostDto = new OrderItemCostDto();
                BeanUtils.copyProperties(it, orderItemCostDto);

                // 应收运费单价(原始价格(无牌无液无电)+特殊加价+明佣)
                BigDecimal receivableOneSeaFreight = it.getOriginalSeaFreight().add(it.getElectrifiedFreightPrice())
                        .add(it.getLiquidFreightPrice()).add(it.getBrandFreightPrice()).add(it.getPlainCommission());
                orderItemCostDto.setReceivableOneSeaFreight(receivableOneSeaFreight);
                // 优惠运费单价, 因成交单价可能是特价，这里优惠单价就不是单指优惠活动的优惠了，需要应收单价-成交单价=实际优惠单价
                orderItemCostDto.setDiscountFreightPrice(orderItemCostDto.getReceivableOneSeaFreight().subtract(orderItemCostDto.getOneSeaFreight()));
                // 应收清关费单价(原始价格(无牌无液无电)+特殊加价)
                BigDecimal receivableOneClearanceFreight = it.getOriginalClearanceFreight().add(it.getElectrifiedClearanceFeePrice())
                        .add(it.getLiquidClearanceFeePrice()).add(it.getBrandClearanceFeePrice());
                orderItemCostDto.setReceivableOneClearanceFreight(receivableOneClearanceFreight);
                // 优惠清关费单价，因成交单价可能是特价，这里优惠单价就不是单指优惠活动的优惠了，需要应收单价-成交单价=实际优惠单价
                orderItemCostDto.setDiscountClearanceFeePrice(orderItemCostDto.getReceivableOneClearanceFreight().subtract(orderItemCostDto.getOneClearanceFreight()));

                orderItemCostDto.setReceivableSeaFreight(it.getReceivableSeaFreight().setScale(0, RoundingMode.HALF_UP));
                orderItemCostDto.setRealitySeaFreight(it.getSeaFreight().setScale(0, RoundingMode.HALF_UP));
                orderItemCostDto.setReceivableClearanceFreight(it.getReceivableClearanceFreight().setScale(0, RoundingMode.HALF_UP));
                orderItemCostDto.setRealityClearanceFreight(it.getClearanceFreight().setScale(0, RoundingMode.HALF_UP));
                if (Objects.nonNull(warehouseInInfoVO)) {
                    // 入仓实测数据
                    orderItemCostDto.setWarehouseInNum(Objects.nonNull(warehouseInInfoVO.getCartonsNum()) ? warehouseInInfoVO.getCartonsNum() : 0);
                    orderItemCostDto.setWarehouseInQuantity(Objects.nonNull(warehouseInInfoVO.getQuantityAll()) ? warehouseInInfoVO.getQuantityAll() : 0);
                    orderItemCostDto.setWarehouseInWeight(Objects.nonNull(warehouseInInfoVO.getWeight()) ? warehouseInInfoVO.getWeight() : BigDecimal.ZERO);
                    orderItemCostDto.setWarehouseInVolume(Objects.nonNull(warehouseInInfoVO.getVolume()) ? warehouseInInfoVO.getVolume() : BigDecimal.ZERO);
                    // 实收数据
                    orderItemCostDto.setRealityChargeNum(Objects.nonNull(warehouseInInfoVO.getCartonsNum()) ? warehouseInInfoVO.getCartonsNum() : 0);
                    orderItemCostDto.setRealityChargeQuantity(it.getChargeQuantity().compareTo(it.getMinMeteringQuantity()) < 0 ? it.getMinMeteringQuantity() : it.getChargeQuantity());
                    orderItemCostDto.setRealityChargeWeight(it.getChargeWeight().compareTo(it.getMinMeteringWeight()) < 0 ? it.getMinMeteringWeight() : it.getChargeWeight());
                    orderItemCostDto.setRealityChargeVolume(it.getChargeVolume().compareTo(it.getMinMeteringVolume()) < 0 ? it.getMinMeteringVolume() : it.getChargeVolume());
                    // 应收数据
                    orderItemCostDto.setOrgChargeNum(Objects.nonNull(warehouseInInfoVO.getCartonsNum()) ? warehouseInInfoVO.getCartonsNum() : 0);
                    if (Objects.isNull(it.getOrgChargeQuantity()) || it.getOrgChargeQuantity().compareTo(BigDecimal.ZERO) == 0) {
                        orderItemCostDto.setOrgChargeQuantity(it.getChargeQuantity());
                    } else {
                        orderItemCostDto.setOrgChargeQuantity(it.getOrgChargeQuantity());
                    }
                    // 应收数据只有体积和重量会根据重泡货标准重新计算
                    if (Objects.isNull(it.getOrgChargeWeight()) || it.getOrgChargeWeight().compareTo(BigDecimal.ZERO) == 0) {
                        orderItemCostDto.setOrgChargeWeight(it.getChargeWeight());
                    } else {
                        orderItemCostDto.setOrgChargeWeight(it.getOrgChargeWeight());
                    }
                    if (Objects.isNull(it.getOrgChargeVolume()) || it.getOrgChargeVolume().compareTo(BigDecimal.ZERO) == 0) {
                        orderItemCostDto.setOrgChargeVolume(it.getChargeVolume());
                    } else {
                        orderItemCostDto.setOrgChargeVolume(it.getOrgChargeVolume());
                    }
                }
                // TODO 转化封装，待后面优化查询
                if (freightReceivableDOMap.containsKey(it.getOrderItemId())) {
                    ReceivableDO freightReceivableDO = freightReceivableDOMap.get(it.getOrderItemId());
                    if (Objects.nonNull(freightReceivableDO)) {
                        BigDecimal discountFee = Objects.isNull(freightReceivableDO.getDiscountTotal()) ? BigDecimal.ZERO : freightReceivableDO.getDiscountTotal();
                        orderItemCostDto.setReceiptDiscountFreightPrice(discountFee);
                        orderItemCostDto.setRealitySeaFreight(orderItemCostDto.getRealitySeaFreight().subtract(discountFee));
                    } else {
                        orderItemCostDto.setReceiptDiscountFreightPrice(BigDecimal.ZERO);
                    }
                }
                if (clearanceReceivableDOMap.containsKey(it.getOrderItemId())) {
                    ReceivableDO clearanceReceivableDO = clearanceReceivableDOMap.get(it.getOrderItemId());
                    if (Objects.nonNull(clearanceReceivableDO)) {
                        BigDecimal discountFee = Objects.isNull(clearanceReceivableDO.getDiscountTotal()) ? BigDecimal.ZERO : clearanceReceivableDO.getDiscountTotal();
                        orderItemCostDto.setReceiptDiscountClearanceFeePrice(discountFee);
                        orderItemCostDto.setRealityClearanceFreight(orderItemCostDto.getRealityClearanceFreight().subtract(discountFee));
                    } else {
                        orderItemCostDto.setReceiptDiscountClearanceFeePrice(BigDecimal.ZERO);
                    }
                }
                // 优惠运费
                orderItemCostDto.setTotalDiscountFreightPrice(Objects.isNull(orderItemCostDto.getReceivableSeaFreight())
                        || orderItemCostDto.getReceivableSeaFreight().compareTo(BigDecimal.ZERO) == 0 ?
                        BigDecimal.ZERO : orderItemCostDto.getReceivableSeaFreight().subtract(orderItemCostDto.getRealitySeaFreight()));
                // 优惠清关费
                orderItemCostDto.setTotalDiscountClearanceFeePrice(Objects.isNull(orderItemCostDto.getReceivableClearanceFreight())
                        || orderItemCostDto.getReceivableClearanceFreight().compareTo(BigDecimal.ZERO) == 0 ?
                        BigDecimal.ZERO : orderItemCostDto.getReceivableClearanceFreight().subtract(orderItemCostDto.getRealityClearanceFreight()));
                // TODO 应收运费与清关费
                orderItemCostDtoList.add(orderItemCostDto);
            }
            detailSummaryDto.setOrderItemCostDtoList(orderItemCostDtoList);
            // 优惠信息列表
            detailSummaryDto.setCouponInfoVOList(couponInfoVOList);
        }

        // TODO 特价审批记录列表
        // 只获取优惠与管理折扣的特价记录
        List<OrderApprovalDO> approvalDOList = orderApprovalMapper.approvalListBytTypeAndStatus(orderId, Arrays.asList(1, 2, 31, 32), 2);
        List<OrderSpecialApplyVO> allSpecialApplyVOList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(approvalDOList)) {
            List<OrderSpecialApplyVO> orderSpecialApplyVOList = approvalDOList.stream().filter(val -> val.getType() == 1 || val.getType() == 2)
                    .map(approval -> {
                        OrderSpecialApplyVO specialApplyVO = JSONObject.parseObject(approval.getDetails(), OrderSpecialApplyVO.class);
                        if (Objects.nonNull(specialApplyVO)) {
                            specialApplyVO.setCreatorName(approval.getCreatorName());
                            specialApplyVO.setCreateTime(approval.getCreateTime());
                        }
                        return specialApplyVO;
                    }).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(orderSpecialApplyVOList)) {
                allSpecialApplyVOList.addAll(orderSpecialApplyVOList);
            }
            List<OrderApprovalDO> batchApprovalDOList = approvalDOList.stream().filter(val -> val.getType() == 31 || val.getType() == 32).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(batchApprovalDOList)) {
                for (OrderApprovalDO orderApprovalDO : batchApprovalDOList) {
                    OrderSpecialBatchApplyVO orderSpecialBatchApplyVO = JSONObject.parseObject(orderApprovalDO.getDetails(), OrderSpecialBatchApplyVO.class);
                    OrderApprovalHeadBaseVO orderApprovalHeadBaseVO = orderSpecialBatchApplyVO.getOrderApprovalHeadBaseVO();
                    List<OrderSpecialBatchApplyOrderItemDetailVO> batchApplyOrderItemDetailVOList = orderSpecialBatchApplyVO.getBatchApplyOrderItemDetailVOList();
                    if (CollectionUtil.isNotEmpty(batchApplyOrderItemDetailVOList)) {
                        List<OrderSpecialApplyVO> batchSpecialApplyVOList = batchApplyOrderItemDetailVOList.stream().map(item -> {
                            OrderSpecialApplyVO specialApplyVO = new OrderSpecialApplyVO();
                            BeanUtils.copyProperties(item, specialApplyVO);
                            specialApplyVO.setOrderApprovalHeadBaseVO(orderApprovalHeadBaseVO);
                            specialApplyVO.setOrderNo(orderDO.getOrderNo());
                            specialApplyVO.setOrderId(orderId);
                            specialApplyVO.setCreatorName(orderApprovalDO.getCreatorName());
                            specialApplyVO.setCreateTime(orderApprovalDO.getCreateTime());
                            return specialApplyVO;
                        }).collect(Collectors.toList());
                        allSpecialApplyVOList.addAll(batchSpecialApplyVOList);
                    }
                }
            }

        }
        detailSummaryDto.setOrderSpecialApplyVOList(allSpecialApplyVOList);
        return detailSummaryDto;
    }

    @NotNull
    private Function<ReceivableDO, OrderReceivableFeeDto> getFeeDtoFunction() {
        return rb -> {
            OrderReceivableFeeDto receivableFeeDto = new OrderReceivableFeeDto();
            BeanUtils.copyProperties(rb, receivableFeeDto);
            receivableFeeDto.setReceivableTotalAmount(rb.getTotalAmount());
            // 当优惠金额不为空并且大于0时，重新计算实收金额，否则实收金额就等于应收金额
            if (Objects.nonNull(receivableFeeDto.getDiscountTotal()) && receivableFeeDto.getDiscountTotal().compareTo(BigDecimal.ZERO) > 0) {
                receivableFeeDto.setRealityTotalAmount(receivableFeeDto.getReceivableTotalAmount().subtract(receivableFeeDto.getDiscountTotal()));
            } else {
                receivableFeeDto.setRealityTotalAmount(receivableFeeDto.getReceivableTotalAmount());
            }
            return receivableFeeDto;
        };
    }

    @Override
    public List<OrderDO> getOrderListByOrderNoList(Collection<String> orderNoList) {
        return orderMapper.selectList(new LambdaQueryWrapper<OrderDO>()
                .in(OrderDO::getOrderNo, orderNoList)
        );
    }


    @Override
    public List<OrderDO> getAirRefreshOrderPrice(List<Integer> transportIdList) {
        return orderMapper.getAirRefreshOrderPrice(transportIdList);
    }

    @Override
    public boolean isSplitOrderChildren(OrderDO orderDO) {
        boolean isSplitSeparateOrder = orderDO.getSplitSeparateOrder();

        //拆单变更不同运输方式后，当做独立订单，可继续拆单、可入仓修改、重新入仓要独立计费。
        //海运拆海运：子订单不包含空运，只有海运，按现有方式，子订单不可入仓修改、不可特价
        //海运拆空运：子订单包含空运，所有子订单按独立订单处理，可入仓修改、可特价
        //空运拆海运：当做独立子订单处理，可入仓修改、可特价
        //空运拆空运：当做独立子订单处理，可入仓修改、可特价
        //有空运订单参与的拆单  都不属于拆单
        if (isSplitSeparateOrder) {
            return false;
        }
        return Objects.nonNull(orderDO.getParentOrderId()) && orderDO.getParentOrderId() != 0L;
    }

    @Override
    public ContainerReportOrderPageResult<OrderCostSummaryDto> containerOrderSummary(ContainerReportOrderQueryVO query, PageVO page) {
        if (Objects.isNull(query.getLang())) {
            query.setLang(I18nMessage.getLang());
        }
        ArrayList<Integer> orderType = new ArrayList<>();
        if (query.getIsHeavyCargo() != null && query.getIsHeavyCargo() == 1) {
            orderType.add(2);
        }
        if (query.getIsPaoCargo() != null && query.getIsPaoCargo() == 1) {
            orderType.add(3);
        }
        query.setOrderType(orderType);
        log.warn(I18nMessage.getLang().toString());
        List<OrderBackPageVO> records = orderMapper.containerOrderSummaryList(query);
        if (CollectionUtil.isEmpty(records)) {
            return ContainerReportOrderPageResult.empty();
        }
        List<OrderCostSummaryDto> totalList = records.stream().map(back -> {
            OrderCostSummaryDto orderCostSummaryDto = this.getOrderCostSummaryDto(null, back);
            orderCostSummaryDto.setIsCargoControl(back.getIsCargoControl() ? 1 : 0);
            return orderCostSummaryDto;
        }).collect(Collectors.toList());
        int startIndex = Math.max(0, (page.getPage() - 1) * page.getRows());
        int endIndex = Math.min(startIndex + page.getRows(), records.size());
        List<OrderCostSummaryDto> resultList = totalList.subList(startIndex, endIndex);
        ContainerReportOrderPageResult<OrderCostSummaryDto> pageResult = new ContainerReportOrderPageResult(resultList, records.size(), page.getRows(), (long) page.getPage(), records.size() / page.getRows() + 1);
        // 汇总全部
        totalList.stream().forEach(orderCostSummaryDto -> {
            boolean isInPage = resultList.contains(orderCostSummaryDto);
            updateContainerReportFeeGroupList(pageResult.getReceivableTotalFeeGroupDtoList(), pageResult.getPageReceivableTotalFeeGroupDtoList(), isInPage, orderCostSummaryDto.getReceivableTotalFeeGroupDtoList());
            updateContainerReportFeeGroupList(pageResult.getDiscountTotalFeeGroupDtoList(), pageResult.getPageDiscountTotalFeeGroupDtoList(), isInPage, orderCostSummaryDto.getDiscountTotalFeeGroupDtoList());
            updateContainerReportFeeGroupList(pageResult.getNetReceiptsTotalFeeGroupDtoList(), pageResult.getPageNetReceiptsTotalFeeGroupDtoList(), isInPage, orderCostSummaryDto.getNetReceiptsTotalFeeGroupDtoList());
            updateContainerReportFeeGroupList(pageResult.getWriteOffTotalFeeGroupDtoList(), pageResult.getPageWriteOffTotalFeeGroupDtoList(), isInPage, orderCostSummaryDto.getWriteOffTotalFeeGroupDtoList());
            updateContainerReportFeeGroupList(pageResult.getNotWriteOffTotalFeeGroupDtoList(), pageResult.getPageNotWriteOffTotalFeeGroupDtoList(), isInPage, orderCostSummaryDto.getNotWriteOffTotalFeeGroupDtoList());
        });
        return pageResult;
    }

    private void updateContainerReportFeeGroupList(List<FeeGroupDto> totalList, List<FeeGroupDto> pageList, boolean isInPage, List<FeeGroupDto> feeGroupDtoList) {
        for (FeeGroupDto feeGroupDto : feeGroupDtoList) {
            int index = totalList.indexOf(feeGroupDto);
            if (index > -1) {
                totalList.get(index).addAmount(feeGroupDto.getAmount());
            } else {
                totalList.add(feeGroupDto);
            }
            if (isInPage) {
                int indexPage = pageList.indexOf(feeGroupDto);
                if (indexPage > -1) {
                    pageList.get(indexPage).addAmount(feeGroupDto.getAmount());
                } else {
                    pageList.add(feeGroupDto);
                }
            }
        }
    }
}
