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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.apollo.core.dto.OrderDto;
import cn.iocoder.yudao.framework.apollo.core.event.*;
import cn.iocoder.yudao.framework.apollo.core.event.Order.CalculateOrderYeJiTypeEvent;
import cn.iocoder.yudao.framework.apollo.core.event.Order.OrderApprovalTypeCheckEvent;
import cn.iocoder.yudao.framework.apollo.core.event.Order.OrderAssociationOfferInfoEvent;
import cn.iocoder.yudao.framework.apollo.core.event.box.BoxCheckOrderApprovalEvent;
import cn.iocoder.yudao.framework.apollo.core.event.box.BoxOrderDynamicEstTimeEvent;
import cn.iocoder.yudao.framework.apollo.core.event.warehouseIn.WarehouseInOrderChangeChannelEvent;
import cn.iocoder.yudao.framework.apollo.core.event.warehouseIn.WarehouseInOrderChangeTransportEvent;
import cn.iocoder.yudao.framework.common.util.spring.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.util.bigDecimal.BigDecimalUtils;
import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO;
import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
import cn.iocoder.yudao.framework.i18n.core.I18nMessage;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.service.AbstractService;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.bpm.api.BpmCreateServiceFactory;
import cn.iocoder.yudao.module.bpm.enums.WorkFlowEmus;
import cn.iocoder.yudao.module.bpm.resp.TaskResp;
import cn.iocoder.yudao.module.customer.dal.dataobject.customer.CustomerDO;
import cn.iocoder.yudao.module.customer.dal.dataobject.customerContacts.CustomerContactsDO;
import cn.iocoder.yudao.module.customer.dal.dataobject.customerOperateLog.CustomerOperateLogDO;
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.customerCreditLog.CustomerCreditLogService;
import cn.iocoder.yudao.module.customer.service.customerOperateLog.CustomerOperateLogService;
import cn.iocoder.yudao.module.customer.service.indirectCustomer.IndirectCustomerService;
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.dto.LogisticsInfoDto;
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.customer.CustomerApi;
import cn.iocoder.yudao.module.ecw.api.unit.UnitApi;
import cn.iocoder.yudao.module.ecw.api.unit.dto.UnitRespDto;
import cn.iocoder.yudao.module.ecw.dal.dataobject.country.CountryDO;
import cn.iocoder.yudao.module.ecw.dal.dataobject.region.RegionDO;
import cn.iocoder.yudao.module.ecw.dal.dataobject.supplier.SupplierDO;
import cn.iocoder.yudao.module.ecw.service.country.CountryService;
import cn.iocoder.yudao.module.ecw.service.paramValid.ParamValidatorService;
import cn.iocoder.yudao.module.ecw.service.region.RegionService;
import cn.iocoder.yudao.module.ecw.service.supplier.SupplierService;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
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.dal.dataobject.approval.OrderApprovalDO;
import cn.iocoder.yudao.module.order.dal.dataobject.order.OrderDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderCargoControl.OrderCargoControlDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderCargoControlPick.OrderCargoControlPickDO;
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.orderFeeApplication.OrderFeeApplicationDO;
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.orderOperateLog.OrderOperateLogDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderPickup.OrderPickupDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderSpecialNeed.OrderSpecialNeedDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderTime.OrderTimeDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderWarehouseApproval.OrderWarehouseApprovalDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderWarehouseIn.OrderWarehouseInDO;
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.orderCargoControl.OrderCargoControlMapper;
import cn.iocoder.yudao.module.order.dal.mysql.orderCargoControlPick.OrderCargoControlPickMapper;
import cn.iocoder.yudao.module.order.dal.mysql.orderItem.OrderItemMapper;
import cn.iocoder.yudao.module.order.dal.mysql.orderPickup.OrderPickupMapper;
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.dal.mysql.targetLog.TargetLogMapper;
import cn.iocoder.yudao.module.order.dto.OrderBackInfoDto;
import cn.iocoder.yudao.module.order.enums.*;
import cn.iocoder.yudao.module.order.service.approval.OrderApprovalService;
import cn.iocoder.yudao.module.order.param.OrderChangePriceParam;
import cn.iocoder.yudao.module.order.service.order.*;
import cn.iocoder.yudao.module.order.service.orderException.OrderExceptionService;
import cn.iocoder.yudao.module.order.service.orderOperateLog.OrderOperateLogService;
import cn.iocoder.yudao.module.order.service.orderWarehouseApproval.OrderWarehouseApprovalService;
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.orderConsignor.OrderConsignorBackVO;
import cn.iocoder.yudao.module.order.vo.orderDeparture.OrderDepartureBackVO;
import cn.iocoder.yudao.module.order.vo.orderException.OrderExceptionCreateReqVO;
import cn.iocoder.yudao.module.order.vo.orderException.OrderExceptionDescVO;
import cn.iocoder.yudao.module.order.vo.orderItem.OrderItemCreateReqVO;
import cn.iocoder.yudao.module.order.vo.orderItem.OrderItemInWarehouseVO;
import cn.iocoder.yudao.module.order.vo.orderObjective.OrderObjectiveBackVO;
import cn.iocoder.yudao.module.order.vo.orderSpecialNeed.OrderSpecialNeedCreateReqVO;
import cn.iocoder.yudao.module.order.vo.orderWarehouseIn.OrderWarehouseInSumBackVO;
import cn.iocoder.yudao.module.product.dto.FeeDto;
import cn.iocoder.yudao.module.product.enums.FeeTypeEnum;
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.wealth.dal.dataobject.receivable.ReceivableDO;
import cn.iocoder.yudao.module.wealth.enums.BoxAirStatusEnum;
import cn.iocoder.yudao.module.wealth.service.receivable.ReceivableService;
import cn.iocoder.yudao.module.wealth.vo.receivable.ReceivableCreateReqVO;
import cn.iocoder.yudao.module.wealth.vo.receivable.ReceivableQueryVO;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
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.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static cn.iocoder.yudao.framework.apollo.core.constants.Constants.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.order.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.order.enums.OrderApprovalTypeEnum.ORDER_UPDATE;
import static cn.iocoder.yudao.module.order.enums.OrderApprovalTypeResultEnum.*;
import static cn.iocoder.yudao.module.order.enums.OrderStatusEnum.DRAFT;

/**
 * 订单 Service 实现类
 *
 * @author 系统管理员
 */
@Service
@Validated
@AllArgsConstructor
@Slf4j
public class OrderServiceImpl extends AbstractService<OrderMapper, OrderDO> implements OrderService {

    private final OrderMapper orderMapper;
    private final OrderBusinessService orderBusinessService;
    private final OrderItemMapper orderItemMapper;
    private final OrderTimeMapper orderTimeMapper;
    private final OrderPickupMapper orderPickupMapper;
    private final OrderWarehouseInMapper orderWarehouseInMapper;
    private final OrderGuanlianService orderGuanlianService;
    private final OrderMutualService orderMutualService;
    private final OrderDepartureService orderDepartureService;
    private final OrderObjectiveService orderObjectiveService;
    private final OrderConsignorService orderConsignorService;
    private final OrderCargoControlMapper orderCargoControlMapper;
    private final OrderCargoControlPickMapper orderCargoControlPickMapper;
    private final OrderConsigneeService orderConsigneeService;
    private final WarehouseLineMapper warehouseLineMapper;
    private final ZhongPaoService zhongPaoService;
    private final RegionService regionService;
    private final CustomerContactsService customerContactsService;
    private final CustomerService customerService;
    private final CustomerOperateLogService customerOperateLogService;
    private final CountryService countryService;
    private final OrderApprovalMapper orderApprovalMapper;
    private final SupplierService supplierService;

    private final OrderApprovalService orderApprovalService;
    private final BpmCreateServiceFactory bpmCreateServiceFactory;
    private final ReceivableService receivableService;
    private final OrderFeeApplicationService feeApplicationService;
    private final CustomerApi customerApi;
    private final AdminUserApi adminUserApi;
    private final DictDataApi dictDataApi;
    private final OrderSpecialNeedService orderSpecialNeedService;
    private final CustomerCreditLogService customerCreditLogService;
    private final ParamValidatorService paramValidatorService;
    private final OrderExceptionService orderExceptionService;
    private final OrderWarehouseApprovalService orderWarehouseApprovalService;
    private final ApplicationContext applicationContext;
    private final IndirectCustomerService indirectCustomerService;
    private final CurrencyApi currencyApi;
    private final OrderQueryService orderQueryService;
    private final UnitApi unitApi;
    private final OrderOperateLogService orderOperateLogService;
    private TargetLogMapper targetLogMapper;

    /*
     后台创建订单 memberUserDO 信息为空

     ecw_admin_client 临时放置创建的收货人，发货人联系人信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderDO createOrder(OrderCreateReqVO createReqVO,
                               MemberUserDO memberUserDO) {
        int type = 1;
        //获取功能开关
        List<DictDataRespDTO> dictList =
                dictDataApi.getDictDatas("part_function_switch");
        //智慧预装功能开关
        DictDataRespDTO dictDataRespDTO = dictList.stream().filter(
                        dto -> "create_order_phone_limit".equals(dto.getLabel())).findFirst().
                orElse(null);

        if (createReqVO.getHasConsignee() && Objects.nonNull(createReqVO.getIsCargoControl()) &&
                createReqVO.getIsCargoControl() &&
                Objects.nonNull(dictDataRespDTO) &&
                StringUtils.equals(dictDataRespDTO.getValue(), "11")
                && StringUtils.isNotBlank(createReqVO.getCountryCode())
                && StringUtils.equals("86", createReqVO.getCountryCode())) {
            throw exception(CONSIGNEE_PHONE_IS_EXTERNAL);
        }
        LogisticsInfoDto logisticsInfoDto =
                warehouseLineMapper.getStartInfoAndDestInfoByLineId(
                        createReqVO.getLineId());
        if (Objects.isNull(logisticsInfoDto)) {
            throw exception(ORDER_LINE_NOT_EXIST);
        }
        if (!Objects.equals(logisticsInfoDto.getStartCityId(),
                createReqVO.getDepartureId()) || !Objects.equals(
                logisticsInfoDto.getDestCityId(), createReqVO.getObjectiveId())) {
            throw exception(ORDER_DEPARTURE_OBJECTIVE_AND_LINE_NOT_AGREEMENT);
        }
        if (createReqVO.getIsExternalWarehouse() != null &&
                createReqVO.getIsExternalWarehouse() &&
                StringUtils.isNotBlank(createReqVO.getType()) && createReqVO.getType().contains("1")) {
            throw exception(EXTERNAL_WAREHOUSE_AND_CONCENTRATE_TRANSPORT_NOT_PARALLEL);
        }
        if (createReqVO.getIsExternalWarehouse() != null &&
                createReqVO.getIsExternalWarehouse() && !Objects.equals(createReqVO.getStatus(), DRAFT.getValue())) {
            // 校验外部仓信息是否为空
            if (CollectionUtil.isEmpty(createReqVO.getExternalWarehouseDtoList())) {
                throw exception(ORDER_EXTERNAL_WAREHOUSE_NOT_NULL);
            }
            long count = createReqVO.getExternalWarehouseDtoList().stream()
                    .filter(dto -> Objects.isNull(dto.getEstLoadingTime()) ||
                            StringUtils.isBlank(dto.getLoadingAddress())).count();
            if (count > 0) {
                throw exception(ORDER_EXTERNAL_WAREHOUSE_ADDRESS_AND_LOADING_TIME_NOT_NULL);
            }
        } else {
            if (Objects.isNull(createReqVO.getDeliveryDate()) &&
                    !Objects.equals(createReqVO.getStatus(),
                            DRAFT.getValue())) {
                throw exception(ORDER_DELIVERY_DATE_NOT_NULL);
            }
        }
        if (Objects.equals(TransportTypeShortEnum.SEA_CONTAINER.getValue(),
                createReqVO.getTransportId()) ||
                Objects.equals(TransportTypeShortEnum.MARINE_CONTAINER.getValue(),
                        createReqVO.getTransportId())) {

            //非空运订单，对前端传值的空运参数做格式化处理
            createReqVO.setPortDestCustomsClear(0);
            createReqVO.setDeliveryWay(0);
            createReqVO.setDoubleClear(0);
            createReqVO.setDoubleClear(0);
            createReqVO.setIsSingleTicketTransport(false);
            createReqVO.setIsUnpack(false);
            createReqVO.setCustomsClearCertRemarks("");
            createReqVO.setCustomsClearCert(false);
            createReqVO.setAirlineCompany(0L);
        }
        List<OrderItemDO> orderItemDOList =
                createReqVO.getOrderItemVOList().stream().map(
                        OrderItemConvert.INSTANCE::convert).collect(Collectors.toList());
        // 插入
        OrderDO order = OrderConvert.INSTANCE.convert(createReqVO);
        if (3 == createReqVO.getDrawee()) {
            // 自定义付款人
            if (CollectionUtil.isNotEmpty(createReqVO.getCustomDraweeVOList())) {
                order.setCustomDrawee(JSONObject.toJSONString(createReqVO.getCustomDraweeVOList()));
            } else {
                if (!Objects.equals(createReqVO.getStatus(), DRAFT.getValue())) {
                    throw exception(ORDER_CUSTOM_DRAWEE_INFO_NOT_NULL);
                }
            }
        }
        // 如果渠道为空,或者非空运订单，则默认给0，只在管理端控制层强制校验空运相关业务渠道必填
        if (Objects.isNull(order.getChannelId()) ||
                order.getTransportId() == 1 ||
                order.getTransportId() == 2) {

            order.setChannelId(0L);
        }

        // 查询始发地与目的地信息
        RegionDO departure = regionService.getRegion(createReqVO.getDepartureId());
        if (Objects.isNull(departure) || (!StrUtil.equals(departure.getType(), "2")
                && !StrUtil.equals(departure.getType(), "3"))) {
            throw exception(DEPARTURE_NOT_EXISTS);
        }
        RegionDO objective = regionService.getRegion(createReqVO.getObjectiveId());

        String newOrderNo;
        if (Objects.equals(createReqVO.getStatus(), DRAFT.getValue())) {
            newOrderNo = "DRAFT-" + System.currentTimeMillis();
        } else {
            newOrderNo = orderBusinessService.saveOrUpdateOrderNo(objective,
                    createReqVO.getTransportId(),
                    createReqVO.getIsExternalWarehouse(),
                    StringUtils.isNotBlank(createReqVO.getType()) && createReqVO.getType().contains("1"));
        }
        order.setOrderNo(newOrderNo);

        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        String creator = String.valueOf(loginUser != null ? loginUser.getId() : null);
        Date now = new Date();
        if (Objects.nonNull(createReqVO.getHarvestMethod()) && createReqVO.getHarvestMethod() == 2) {
            order.setCountry(createReqVO.getCountry());
            order.setProvince(createReqVO.getProvince());
            order.setCity(createReqVO.getCity());
            order.setConsigneeAddress(createReqVO.getConsigneeAddress());
        } else {
            order.setCountry(0L);
            order.setProvince(0L);
            order.setCity(0L);
            order.setConsigneeAddress("");
        }
        order.setCreator(creator);
        order.setUpdater(creator);
        order.setCreateTime(now);
        order.setUpdateTime(now);
        orderMapper.insert(order);

        //订单始发地信息
        OrderDepartureDO departureDO = new OrderDepartureDO();
        departureDO.setDepartureId(createReqVO.getDepartureId());
        departureDO.setDeparture(JSONObject.toJSONString(departure));
        departureDO.setDepartureCountryId(logisticsInfoDto.getStartCountryId());
        departureDO.setDepartureWarehouseId(logisticsInfoDto.getStartWarehouseId());
        //订单目的地信息
        OrderObjectiveDO objectiveDO = new OrderObjectiveDO();
        objectiveDO.setObjectiveId(createReqVO.getObjectiveId());
        objectiveDO.setObjective(JSONObject.toJSONString(objective));
        objectiveDO.setObjectiveCountryId(logisticsInfoDto.getDestCountryId());
        objectiveDO.setObjectiveWarehouseId(logisticsInfoDto.getDestWarehouseId());

        departureDO.setCreator(creator);
        departureDO.setUpdater(creator);
        departureDO.setCreateTime(now);
        departureDO.setUpdateTime(now);

        objectiveDO.setCreator(creator);
        objectiveDO.setUpdater(creator);
        objectiveDO.setCreateTime(now);
        objectiveDO.setUpdateTime(now);

        departureDO.setOrderId(order.getOrderId());
        orderDepartureService.save(departureDO);
        objectiveDO.setOrderId(order.getOrderId());
        orderObjectiveService.save(objectiveDO);


        // 当订单的包装类型不为空时，创建特需需要在订单业务执行完成后再进行，避免部分订单数据还未插入
        if (StringUtils.isNotBlank(order.getPackageType())) {
            String[] packageTypes = order.getPackageType().split(StrUtil.COMMA);
            List<OrderSpecialNeedCreateReqVO> createReqVOList = new ArrayList<>();
            for (String packageType : packageTypes) {
                OrderSpecialNeedCreateReqVO reqVO =
                        new OrderSpecialNeedCreateReqVO();
                reqVO.setOrderId(order.getOrderId());
                reqVO.setAdvanceType(packageType);
                reqVO.setTransFee(BigDecimal.ZERO);
                reqVO.setTransCurrency(1);
                reqVO.setTodoDetail(order.getPackageRemarks());
                createReqVOList.add(reqVO);
            }
            orderSpecialNeedService.createOrderSpecialNeed(createReqVOList, Boolean.FALSE);
        }


        if (Objects.isNull(memberUserDO) || null == createReqVO.getUserId()) {
            // admin添加的订单
            this.adminSaveConsignorAndConsignee(createReqVO,
                    order,
                    creator,
                    now,
                    dictDataRespDTO);
        } else {
            // app-web添加的订单
            this.appSaveConsignorAndConsignee(createReqVO, order,
                    creator, now, memberUserDO, dictDataRespDTO);
        }
        if (Objects.isNull(createReqVO.getDisplayBillLadingPrice())) {
            // 查询订单归属客户的默认档案设置
            if (Objects.nonNull(order.getCustomerId()) &&
                    order.getCustomerId() > 0L) {
                CustomerDO customerDO = customerService.getById(order.getCustomerId());
                if (Objects.nonNull(customerDO) &&
                        Objects.nonNull(customerDO.getIsShowTidanPrice())) {
                    order.setDisplayBillLadingPrice(customerDO.getIsShowTidanPrice());
                    order.setIsInOpenSea(customerDO.getIsInOpenSea());
                    order.setYejiType(customerDO.getIsNew() ? 1 : 0);
                }
            }
        }
        orderMapper.updateById(order);


        // 插入订单商品项
        orderBusinessService.costCalculation(creator,
                order, createReqVO.getConsignorId(),
                Objects.isNull(createReqVO.getConsigneeId()) ? 0L : createReqVO.getConsigneeId(),
                createReqVO.getConsignorContactsId(),
                Objects.isNull(createReqVO.getConsigneeContactsId()) ? 0L : createReqVO.getConsigneeContactsId(),
                orderItemDOList, type);


        // 如果报价单id不为空，则表示此订单关联报价单
        if (Objects.nonNull(createReqVO.getOfferId()) &&
                createReqVO.getOfferId() > 0L) {

            applicationContext.publishEvent(
                    new OfferAssociationOrderEvent(createReqVO.getOfferId(),
                            order.getOrderId(),
                            order.getOrderNo(),
                            order.getCreator()));
        }
        try {
            if (memberUserDO != null && null != createReqVO.getUserId()) {
                // app-web添加的订单

                AdminClientCreateEvent adminClientCreateEvent =
                        new AdminClientCreateEvent();
                //下单用户
                adminClientCreateEvent.setUid(createReqVO.getUserId());

                //收货人信息
                OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(
                        new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, order.getOrderId()).orderByDesc(OrderConsigneeDO::getId).last("limit 1"));
                adminClientCreateEvent.setName(orderConsigneeDO.getName());
                adminClientCreateEvent.setCompany(orderConsigneeDO.getCompany());
                adminClientCreateEvent.setMaitou(order.getMarks());
                adminClientCreateEvent.setPhone(orderConsigneeDO.getPhone());
                adminClientCreateEvent.setEmail(orderConsigneeDO.getEmail());
                adminClientCreateEvent.setAddress(orderConsigneeDO.getAddress());
                adminClientCreateEvent.setDialCode(Integer.parseInt(orderConsigneeDO.getCountryCode()));
                adminClientCreateEvent.setDefaultContact(true);

                indirectCustomerService.createIndirectCustomer(
                        adminClientCreateEvent);

            }
        } catch (Exception e) {
            log.error("");
        }


        //非草稿状态下才更新客户状态及其他数据
        if (!DRAFT.getValue().equals(order.getStatus())) {
            Set<Long> idSet = Stream.of(createReqVO.getConsignorId(), createReqVO.getConsigneeId(), order.getCustomerId()).filter(Objects::nonNull).collect(Collectors.toSet());
            for (Long id : idSet) {
                customerService.updateCustomerByCreateOrder(id, order.getOrderId(), order.getOrderNo(), order.getCreateTime());
            }
        }

        // 更新特需
//        this.saveOrUpdateSpecialNeed(order.getOrderId(), order.getPackageType(), order.getPackageRemarks(), creator, now);

        // 创建订单时如果状态为下单更新日志事件
        if (Objects.equals(OrderStatusEnum.ORDER_PLACED.getValue(), order.getStatus())) {
            if (Objects.equals(TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue(), createReqVO.getTransportId())
                    || Objects.equals(TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue(), createReqVO.getTransportId())) {
                if (Objects.isNull(order.getChannelId()) || 0 == order.getChannelId()) {
                    // 当前空运或海空联运订单下单时，没有渠道id，则生成渠道异常
                    OrderExceptionCreateReqVO orderExceptionCreateReqVO =
                            this.genOrderException(order.getOrderId(), order, null, null, OrderExceptionEnum.CHANNEL_EXCEPTION,
                                    "未选择线路渠道", "No route channel selected");
                    orderExceptionService.createOrderException(orderExceptionCreateReqVO);
                }
            }
            if (Objects.equals(TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue(), createReqVO.getTransportId())) {
                orderBusinessService.addAirOrderTimeLog(order, OrderAirTimeEnum.AIR_ORDER_PLACED, null, null, null, null, now, null);
            } else if (Objects.equals(TransportTypeShortEnum.SEA_CONTAINER.getValue(), createReqVO.getTransportId())) {
                orderBusinessService.addSeaOrderTimeLog(order, OrderSeaTimeEnum.SEA_ORDER_PLACED, null, null, null, null, now, null);
            } else {
                orderBusinessService.addOrderTimeLog(order.getStatus(), order, 0, now, now);
            }
        }

        //发货人的信用日志
        customerCreditLogService.sendPackageCreditLog(createReqVO.getConsignorContactsId(), order.getOrderId(), order.getOrderNo());

        // 创建订单操作日志
        orderBusinessService.addOrderOperateLog(order.getOrderId(),
                "新建订单", null);

        //在创建完订单号，计算订单业绩类型
        CalculateOrderYeJiTypeEvent even = new CalculateOrderYeJiTypeEvent();
        even.setOrderId(order.getOrderId());
        applicationContext.publishEvent(even);
        // 返回
        return order;
    }

    /*
     处理发货人和收货人信息
     */
    private void appSaveConsignorAndConsignee(OrderCreateReqVO createReqVO,
                                              OrderDO order,
                                              String creator,
                                              Date now,
                                              MemberUserDO memberUserDO,
                                              DictDataRespDTO dictDataRespDTO) {
        // 根据会员ID获取客户联系人ID与客户ID
        CustomerContactsDO customerContacts =
                customerContactsService.getOne(new LambdaQueryWrapper<CustomerContactsDO>()
                        .and(we -> we.eq(CustomerContactsDO::getUserid, memberUserDO.getId())
                                .or()
                                .eq(CustomerContactsDO::getPhoneNew, memberUserDO.getMobile())
                                .eq(CustomerContactsDO::getAreaCode, memberUserDO.getAreaCode())).eq(CustomerContactsDO::getDeleted, 0).last("limit 1"));

        OrderConsignorDO orderConsignorDO = new OrderConsignorDO();
        orderConsignorDO.setOrderId(order.getOrderId());
        orderConsignorDO.setCreator(creator);
        orderConsignorDO.setUpdater(creator);
        CustomerDO consignorCustomerDO = null;
        if (Objects.isNull(customerContacts)) {
            // 如果客户联系人为空，则创建新的客户信息，重新查询
            customerApi.associateCustomerAuto(memberUserDO.getAreaCode(),
                    memberUserDO.getMobile(), memberUserDO.getId(),
                    memberUserDO.getNickname(), memberUserDO.getCode());
            customerContacts = customerContactsService.getOne(new LambdaQueryWrapper<CustomerContactsDO>()
                    .and(we -> we.eq(CustomerContactsDO::getUserid, memberUserDO.getId())
                            .or()
                            .eq(CustomerContactsDO::getPhoneNew, memberUserDO.getMobile())
                            .eq(CustomerContactsDO::getAreaCode, memberUserDO.getAreaCode())).eq(CustomerContactsDO::getDeleted, 0).last("limit 1"));
        }
        boolean hasConsignee = Objects.nonNull(createReqVO.getHasConsignee()) ? createReqVO.getHasConsignee() : true;
        if (Objects.nonNull(customerContacts)) {
            //发货人联系人
            consignorCustomerDO = customerService.getCustomer(customerContacts.getCustomerId());
            if (consignorCustomerDO != null) {
                orderConsignorDO.setCompany(consignorCustomerDO.getCompany());
                orderConsignorDO.setCompanyEn(consignorCustomerDO.getCompanyEn());
                orderConsignorDO.setCustomerNumber(consignorCustomerDO.getNumber());
                CountryDO consignorCountryDO = countryService.getById(consignorCustomerDO.getCountry());
                if (consignorCountryDO != null) {
                    orderConsignorDO.setCountryAbbreviation(consignorCountryDO.getNameShort());
                }
            }
            if (StringUtils.isBlank(customerContacts.getPhoneNew())) {
                throw exception(CONSIGNOR_PHONE_NOT_NULL);
            }
            if (StringUtils.isBlank(customerContacts.getAreaCode())) {
                throw exception(CONSIGNOR_PHONE_CODE_NOT_NULL);
            }
            orderConsignorDO.setEmail(customerContacts.getEmail());
            orderConsignorDO.setCustomerContactsId(customerContacts.getId());
            orderConsignorDO.setCustomerId(customerContacts.getCustomerId());
        }
        orderConsignorDO.setName(memberUserDO.getNickname());
        orderConsignorDO.setNameEn(memberUserDO.getEnglishName());
        orderConsignorDO.setCountryCode(memberUserDO.getAreaCode());
        orderConsignorDO.setPhone(memberUserDO.getMobile());
        if (StringUtils.isNotBlank(memberUserDO.getEmail())) {
            orderConsignorDO.setEmail(memberUserDO.getEmail());
        }
        if (StringUtils.isNotBlank(memberUserDO.getEnterpriseName())) {
            orderConsignorDO.setCompany(memberUserDO.getEnterpriseName());
        }
        if (StringUtils.isNotBlank(memberUserDO.getEnterpriseNameEn())) {
            orderConsignorDO.setCompanyEn(memberUserDO.getEnterpriseNameEn());
        }
        orderConsignorDO.setRelationId(createReqVO.getUserId());
        orderConsignorDO.setCreateTime(now);
        orderConsignorDO.setUpdateTime(now);
        if (StringUtils.isBlank(orderConsignorDO.getPhone()) || StringUtils.isBlank(orderConsignorDO.getCountryCode())) {
            throw exception(ORDER_CONSIGNOR_PHONE_INFO_NOT_COMPLETE);
        }
        if (StringUtils.isBlank(orderConsignorDO.getName())) {
            throw exception(ORDER_CONSIGNOR_NAME_NOT_COMPLETE);
        }

        try {
            String mobileCode = orderConsignorDO.getCountryCode() + StrUtil.COLON + orderConsignorDO.getPhone();
            paramValidatorService.validatorMobile(mobileCode);
        } catch (Exception e) {
            throw exception(ORDER_CONSIGNOR_PHONE_INCORRECT_FORMAT);
        }
        orderConsignorService.save(orderConsignorDO);
        if (order.getIsCargoControl()) {
            // 控货订单 添加控货人信息 ecw_order_cargo_control
            OrderCargoControlDO orderCargoControlDO = new OrderCargoControlDO();
            BeanUtils.copyProperties(orderConsignorDO, orderCargoControlDO);
            orderCargoControlDO.setId(null); // 置空主键ID
            orderCargoControlDO.setDialCode(Integer.valueOf(orderConsignorDO.getCountryCode()));
            orderCargoControlDO.setIso2(orderConsignorDO.getCountryAbbreviation());
            orderCargoControlDO.setOrderNo(order.getOrderNo());
            orderCargoControlDO.setTidanNo(order.getTidanNo());
            orderCargoControlDO.setCreator(creator);
            orderCargoControlDO.setCreateTime(now);
            orderCargoControlDO.setIsActual(Boolean.TRUE);
            orderCargoControlMapper.insert(orderCargoControlDO);
        }
        OrderConsigneeDO orderConsigneeDO = null;
        // 当订单为控货订单，且发货人客户档案未设置控货无收货人，则需要校验收货人信息
        if (!order.getIsCargoControl() || hasConsignee) {
            // 控货订单有收货人则限制修改收货人
            if (order.getIsCargoControl() && hasConsignee) {
                order.setIsLimitUpdateConsignee(Boolean.TRUE);
            } else {
                order.setIsLimitUpdateConsignee(Boolean.FALSE);
            }
            orderConsigneeDO = new OrderConsigneeDO();
            orderConsigneeDO.setOrderId(order.getOrderId());
            orderConsigneeDO.setCreator(creator);
            orderConsigneeDO.setUpdater(creator);

            if (StringUtils.isBlank(createReqVO.getConsigneePhone())) {
                throw exception(CONSIGNEE_PHONE_NOT_NULL);
            }
            if (StringUtils.isBlank(createReqVO.getCountryCode())) {
                throw exception(CONSIGNEE_PHONE_CODE_NOT_NULL);
            }
            orderConsigneeDO.setPhone(createReqVO.getConsigneePhone());
            orderConsigneeDO.setName(StringUtils.isNotBlank(createReqVO.getConsigneeName()) ? createReqVO.getConsigneeName() : createReqVO.getConsigneePhone());
            orderConsigneeDO.setNameEn(createReqVO.getConsigneeNameEn());
            orderConsigneeDO.setCountryCode(createReqVO.getCountryCode());
            orderConsigneeDO.setEmail(createReqVO.getConsigneeEmail());
            orderConsigneeDO.setCompany(createReqVO.getConsigneeCompany());
            orderConsigneeDO.setCompanyEn(createReqVO.getConsigneeCompanyEn());

            orderConsigneeDO.setHarvestMethod(createReqVO.getHarvestMethod()); // 收货方式
            if (Objects.nonNull(createReqVO.getHarvestMethod()) && createReqVO.getHarvestMethod() == 2) {
                if (StringUtils.isNotBlank(createReqVO.getConsigneeAddress())) {
                    orderConsigneeDO.setAddress(createReqVO.getConsigneeAddress());
                }
            } else {
                orderConsigneeDO.setAddress("");
            }
            orderConsigneeDO.setCountry(createReqVO.getCountry());
            orderConsigneeDO.setProvince(createReqVO.getProvince());
            orderConsigneeDO.setCity(createReqVO.getCity());
            orderConsigneeDO.setRelationId(createReqVO.getUserId());
            orderConsigneeDO.setCreateTime(now);
            orderConsigneeDO.setUpdateTime(now);
            if (StringUtils.isBlank(orderConsigneeDO.getPhone()) || StringUtils.isBlank(orderConsigneeDO.getCountryCode())) {
                throw exception(ORDER_CONSIGNEE_PHONE_INFO_NOT_COMPLETE);
            }
            if (StringUtils.isBlank(orderConsigneeDO.getName())) {
                throw exception(ORDER_CONSIGNEE_NAME_NOT_COMPLETE);
            }
            if (createReqVO.getHasConsignee() && Objects.nonNull(createReqVO.getIsCargoControl()) && createReqVO.getIsCargoControl() && StringUtils.isNotBlank(orderConsigneeDO.getCountryCode()) &&
                    Objects.nonNull(dictDataRespDTO) && StringUtils.equals(dictDataRespDTO.getValue(), "11") && StringUtils.equals("86", orderConsigneeDO.getCountryCode())) {
                throw exception(CONSIGNEE_PHONE_IS_EXTERNAL);
            }
            try {
                String mobileCode = orderConsigneeDO.getCountryCode() + StrUtil.COLON + orderConsigneeDO.getPhone();
                paramValidatorService.validatorMobile(mobileCode);
            } catch (Exception e) {
                throw exception(ORDER_CONSIGNEE_PHONE_INCORRECT_FORMAT);
            }
            //todo 需要判断手机号唯一性，判断规则：1.区号相同，2.先判断手机号码是否存在，然后再判断：a.如果是0开头，判断是否存在非0开头号码；b.如果非0开头，判断是否存在0开头号码
            CustomerContactsDO consignee = customerService.getUniqueOneAndValidate(orderConsigneeDO.getCountryCode(), orderConsigneeDO.getPhone(), null);

            if (Objects.nonNull(consignee) &&
                    Objects.nonNull(consignee.getCustomerId())) {

                orderConsigneeDO.setCustomerId(consignee.getCustomerId());
                orderConsigneeDO.setCustomerContactsId(consignee.getId());
                CustomerDO consigneeDO = customerService.getCustomer(consignee.getCustomerId());
                if (Objects.nonNull(consigneeDO)) {
                    orderConsignorDO.setCustomerNumber(consigneeDO.getNumber());
                }
            } else {
                // 客户不存在，新增客户联系人信息 orderConsigneeDO中有值
                // 20230511 收货人无客户档案时 判断发货人有无客户经理，没有 生成客户档案，进入待分配。
                // 有客户经理，则暂时不生成客户档案。(放在入仓时处理）
                if (consignorCustomerDO == null ||
                        consignorCustomerDO.getCustomerService() == null ||
                        consignorCustomerDO.getCustomerService() == 0) {

                    //ecw_customer_contacts 客户联系人
                    //创建收货人客户
                    CustomerContactsDO consigeeCustomer =
                            customerService.createConsigeeCustomer(
                                    orderConsigneeDO.getName(),
                                    orderConsigneeDO.getCountryCode(),
                                    orderConsigneeDO.getPhone(),
                                    orderConsigneeDO.getCompany(),
                                    orderConsigneeDO.getEmail(),
                                    consignorCustomerDO,
                                    order.getOrderNo());
                    if (consigeeCustomer != null) {
                        orderConsigneeDO.setCustomerId(consigeeCustomer.getCustomerId());
                        orderConsigneeDO.setCustomerContactsId(consigeeCustomer.getId());
                    }
                }
            }
            orderConsigneeService.save(orderConsigneeDO);
        } else {
            // 控货订单没有收货人则不限制修改收货人
            if (order.getIsCargoControl() && hasConsignee) {
                order.setIsLimitUpdateConsignee(Boolean.TRUE);
            } else {
                order.setIsLimitUpdateConsignee(Boolean.FALSE);
            }
        }
        if (!Objects.equals(createReqVO.getStatus(), DRAFT.getValue())) {
            //customerType 发货人-1 收货人 2
            int customerType = this.checkOrderSalesman(order, createReqVO.getOfferId(), null, null, orderConsignorDO, orderConsigneeDO);
            // 更新所属客户经理(业务员)
            if (!DRAFT.getValue().equals(order.getStatus()) && Objects.nonNull(order.getIsChargeCustomer()) && order.getIsChargeCustomer()) {
                addOrderCustomerService(order, customerType);
            }
        }

    }

    //新增订单 客户联系人处理
    private void adminSaveConsignorAndConsignee(OrderCreateReqVO createReqVO,
                                                OrderDO order,
                                                String creator,
                                                Date now,
                                                DictDataRespDTO dictDataRespDTO) {
        OrderConsignorDO orderConsignorDO = new OrderConsignorDO();
        orderConsignorDO.setOrderId(order.getOrderId());
        orderConsignorDO.setCreator(creator);
        orderConsignorDO.setUpdater(creator);
        CustomerDO consignorDO =
                customerService.getCustomer(createReqVO.getConsignorId());
        boolean hasConsignee = Objects.nonNull(createReqVO.getHasConsignee()) ? createReqVO.getHasConsignee() : true;
        if (Objects.nonNull(consignorDO)) {
            orderConsignorDO.setCompany(consignorDO.getCompany());
            orderConsignorDO.setCompanyEn(consignorDO.getCompanyEn());
            CountryDO consignorCountryDO = countryService.getById(consignorDO.getCountry());
            if (Objects.nonNull(consignorCountryDO)) {
                orderConsignorDO.setCountryAbbreviation(consignorCountryDO.getNameShort());
            }
            orderConsignorDO.setCustomerNumber(consignorDO.getNumber());
        }
        CustomerContactsDO consignorContactsDO =
                customerContactsService.getCustomerContacts(
                        createReqVO.getConsignorContactsId());

        if (Objects.nonNull(consignorContactsDO)) {
            if (StringUtils.isBlank(consignorContactsDO.getPhoneNew())) {
                throw exception(CONSIGNOR_PHONE_NOT_NULL);
            }
            if (StringUtils.isBlank(consignorContactsDO.getAreaCode())) {
                throw exception(CONSIGNOR_PHONE_CODE_NOT_NULL);
            }
            orderConsignorDO.setName(consignorContactsDO.getName());
            orderConsignorDO.setNameEn(consignorContactsDO.getNameEn());
            orderConsignorDO.setCountryCode(consignorContactsDO.getAreaCode());
            orderConsignorDO.setEmail(consignorContactsDO.getEmail());
            orderConsignorDO.setPhone(consignorContactsDO.getPhoneNew());
            orderConsignorDO.setCustomerContactsId(consignorContactsDO.getId());
            orderConsignorDO.setCustomerId(consignorContactsDO.getCustomerId());
        } else {
            if (!Objects.equals(createReqVO.getStatus(),
                    DRAFT.getValue())) {
                if (StringUtils.isBlank(createReqVO.getConsignorPhone())) {
                    throw exception(CONSIGNOR_PHONE_NOT_NULL);
                }
                if (StringUtils.isBlank(createReqVO.getConsignorCountryCode())) {
                    throw exception(CONSIGNOR_PHONE_CODE_NOT_NULL);
                }
            }
            orderConsignorDO.setName(createReqVO.getConsignorName());
            orderConsignorDO.setNameEn(createReqVO.getConsignorNameEn());
            orderConsignorDO.setCountryCode(createReqVO.getConsignorCountryCode());
            orderConsignorDO.setEmail(createReqVO.getConsignorEmail());
        }
        if (!Objects.equals(createReqVO.getStatus(),
                DRAFT.getValue())) {
            if (StringUtils.isBlank(orderConsignorDO.getPhone()) ||
                    StringUtils.isBlank(orderConsignorDO.getCountryCode())) {
                throw exception(ORDER_CONSIGNOR_PHONE_INFO_NOT_COMPLETE);
            }
            if (StringUtils.isBlank(orderConsignorDO.getName())) {
                throw exception(ORDER_CONSIGNOR_NAME_NOT_COMPLETE);
            }
            try {
                String mobileCode = orderConsignorDO.getCountryCode() + StrUtil.COLON + orderConsignorDO.getPhone();
                paramValidatorService.validatorMobile(mobileCode);
            } catch (Exception e) {
                throw exception(ORDER_CONSIGNOR_PHONE_INCORRECT_FORMAT);
            }
        }
        if (StringUtils.isNotBlank(createReqVO.getConsignorName())) {
            orderConsignorDO.setName(createReqVO.getConsignorName());
        }
        if (StringUtils.isNotBlank(createReqVO.getConsignorNameEn())) {
            orderConsignorDO.setNameEn(createReqVO.getConsignorNameEn());
        }
        if (StringUtils.isNotBlank(createReqVO.getConsignorCompany())) {
            orderConsignorDO.setCompany(createReqVO.getConsignorCompany());
        }
        if (StringUtils.isNotBlank(createReqVO.getConsignorCompanyEn())) {
            orderConsignorDO.setCompanyEn(createReqVO.getConsignorCompanyEn());
        }
        if (StringUtils.isNotBlank(createReqVO.getConsignorEmail())) {
            orderConsignorDO.setEmail(createReqVO.getConsignorEmail());
        }
        orderConsignorDO.setRelationId(createReqVO.getUserId());
        orderConsignorDO.setCreateTime(now);
        orderConsignorDO.setUpdateTime(now);
        if (StringUtils.isNotBlank(orderConsignorDO.getPhone())) {
            orderConsignorService.save(orderConsignorDO);
        }
        if (order.getIsCargoControl() &&
                !Objects.equals(createReqVO.getStatus(),
                        DRAFT.getValue())) {

            // 控货订单 添加控货人信息 (当放货人为空时不添加 注:
            // 当报价单赢单创建的草稿订单可能发货人为空)
            OrderCargoControlDO orderCargoControlDO = new OrderCargoControlDO();
            BeanUtils.copyProperties(orderConsignorDO, orderCargoControlDO);
            orderCargoControlDO.setId(null); // 置空主键ID
            orderCargoControlDO.setDialCode(Integer.valueOf(orderConsignorDO.getCountryCode()));
            orderCargoControlDO.setIso2(orderConsignorDO.getCountryAbbreviation());
            orderCargoControlDO.setOrderNo(order.getOrderNo());
            orderCargoControlDO.setTidanNo(order.getTidanNo());
            orderCargoControlDO.setCreator(creator);
            orderCargoControlDO.setCreateTime(now);
            orderCargoControlDO.setIsActual(Boolean.TRUE);
            orderCargoControlMapper.insert(orderCargoControlDO);
            //TODO 订单控货信息日志补充
            String msg = String.format("订单创建默认发货人控货信息，姓名%s，电话+%s", orderConsignorDO.getName() + "/" + (StringUtils.isNotBlank(orderConsignorDO.getNameEn()) ? orderConsignorDO.getNameEn() : "空"),
                    orderConsignorDO.getCountryCode() + orderConsignorDO.getPhone());
            orderBusinessService.createOrderControlLog(orderCargoControlDO.getOrderId(), 1, "创建控货信息", msg, 0L);
        }
        OrderConsigneeDO orderConsigneeDO = null;
        if (!order.getIsCargoControl() || hasConsignee) {
            // 控货订单有收货人则限制修改收货人
            if (order.getIsCargoControl() && hasConsignee) {
                order.setIsLimitUpdateConsignee(Boolean.TRUE);
            } else {
                order.setIsLimitUpdateConsignee(Boolean.FALSE);
            }
            orderConsigneeDO = new OrderConsigneeDO();
            orderConsigneeDO.setOrderId(order.getOrderId());
            orderConsigneeDO.setCreator(creator);
            orderConsigneeDO.setUpdater(creator);
            CustomerDO consigneeDO =
                    customerService.getCustomer(createReqVO.getConsigneeId());
            if (consigneeDO != null) {
                orderConsigneeDO.setCompany(consigneeDO.getCompany());
                orderConsigneeDO.setCompanyEn(consigneeDO.getCompanyEn());
                orderConsigneeDO.setAddress(consigneeDO.getAddress());
                orderConsigneeDO.setCustomerId(consigneeDO.getId());
                orderConsigneeDO.setCustomerNumber(consigneeDO.getNumber());
                CountryDO consigneeCountryDO = countryService.getById(consigneeDO.getCountry());
                if (consigneeCountryDO != null) {
                    orderConsignorDO.setCountryAbbreviation(consigneeCountryDO.getNameShort());
                }
            } else {
                orderConsigneeDO.setCompany(createReqVO.getConsigneeCompany());
                orderConsigneeDO.setCompanyEn(createReqVO.getConsigneeCompanyEn());
                orderConsigneeDO.setAddress(createReqVO.getConsigneeAddress());
                orderConsignorDO.setCountryAbbreviation(createReqVO.getCountryAbbreviation());
            }
            //客户联系人
            CustomerContactsDO consigneeContactsDO =
                    customerContactsService.getCustomerContacts(
                            createReqVO.getConsigneeContactsId());
            if (null != consigneeContactsDO) {
                if (StringUtils.isBlank(consigneeContactsDO.getPhoneNew())) {
                    throw exception(CONSIGNEE_PHONE_NOT_NULL);
                }
                if (StringUtils.isBlank(consigneeContactsDO.getAreaCode())) {
                    throw exception(CONSIGNEE_PHONE_CODE_NOT_NULL);
                }
                orderConsigneeDO.setName(consigneeContactsDO.getName());
                orderConsigneeDO.setNameEn(consigneeContactsDO.getNameEn());
                orderConsigneeDO.setCountryCode(consigneeContactsDO.getAreaCode());
                orderConsigneeDO.setEmail(consigneeContactsDO.getEmail());
                orderConsigneeDO.setPhone(consigneeContactsDO.getPhoneNew());
                orderConsigneeDO.setCustomerContactsId(consigneeContactsDO.getId());
                orderConsigneeDO.setCustomerId(consigneeContactsDO.getCustomerId());
            } else {
                if (!Objects.equals(createReqVO.getStatus(),
                        DRAFT.getValue())) {

                    if (StringUtils.isBlank(createReqVO.getConsigneePhone())) {
                        throw exception(CONSIGNEE_PHONE_NOT_NULL);
                    }
                    if (StringUtils.isBlank(createReqVO.getCountryCode())) {
                        throw exception(CONSIGNEE_PHONE_CODE_NOT_NULL);
                    }
                }
                orderConsigneeDO.setName(createReqVO.getConsigneeName());
                orderConsigneeDO.setNameEn(createReqVO.getConsigneeNameEn());
                orderConsigneeDO.setCountryCode(createReqVO.getCountryCode());
                orderConsigneeDO.setEmail(createReqVO.getConsigneeEmail());
                orderConsigneeDO.setPhone(createReqVO.getConsigneePhone());
            }

            orderConsigneeDO.setHarvestMethod(createReqVO.getHarvestMethod());
            //收货方式
            if (Objects.nonNull(createReqVO.getHarvestMethod()) && createReqVO.getHarvestMethod() == 2) {
                if (StringUtils.isNotBlank(createReqVO.getConsigneeAddress())) {
                    orderConsigneeDO.setAddress(createReqVO.getConsigneeAddress());
                }
            } else {
                orderConsigneeDO.setAddress("");
            }
            orderConsigneeDO.setCountry(createReqVO.getCountry());
            orderConsigneeDO.setProvince(createReqVO.getProvince());
            orderConsigneeDO.setCity(createReqVO.getCity());
            orderConsigneeDO.setRelationId(createReqVO.getUserId());
            orderConsigneeDO.setCreateTime(now);
            orderConsigneeDO.setUpdateTime(now);

            if (!Objects.equals(createReqVO.getStatus(),
                    DRAFT.getValue())) {
                if (StringUtils.isBlank(orderConsigneeDO.getPhone()) ||
                        StringUtils.isBlank(orderConsigneeDO.getCountryCode())) {

                    throw exception(ORDER_CONSIGNEE_PHONE_INFO_NOT_COMPLETE);
                }
                if (StringUtils.isBlank(orderConsigneeDO.getName())) {
                    throw exception(ORDER_CONSIGNEE_NAME_NOT_COMPLETE);
                }
                try {
                    String mobileCode = orderConsigneeDO.getCountryCode() + StrUtil.COLON + orderConsigneeDO.getPhone();
                    paramValidatorService.validatorMobile(mobileCode);
                } catch (Exception e) {
                    throw exception(ORDER_CONSIGNEE_PHONE_INCORRECT_FORMAT);
                }
            }
            if (createReqVO.getHasConsignee() && Objects.nonNull(createReqVO.getIsCargoControl()) && createReqVO.getIsCargoControl() && StringUtils.isNotBlank(orderConsigneeDO.getCountryCode()) &&
                    Objects.nonNull(dictDataRespDTO) && StringUtils.equals(dictDataRespDTO.getValue(), "11") && StringUtils.equals("86", orderConsigneeDO.getCountryCode())) {
                throw exception(CONSIGNEE_PHONE_IS_EXTERNAL);
            }
            if (StringUtils.isNotBlank(createReqVO.getConsigneeName())) {
                orderConsigneeDO.setName(createReqVO.getConsigneeName());
            }
            if (StringUtils.isNotBlank(createReqVO.getConsigneeNameEn())) {
                orderConsigneeDO.setNameEn(createReqVO.getConsigneeNameEn());
            }
            if (StringUtils.isNotBlank(createReqVO.getConsigneeCompany())) {
                orderConsigneeDO.setCompany(createReqVO.getConsigneeCompany());
            }
            if (StringUtils.isNotBlank(createReqVO.getConsigneeCompanyEn())) {
                orderConsigneeDO.setCompanyEn(createReqVO.getConsigneeCompanyEn());
            }
            if (StringUtils.isNotBlank(createReqVO.getConsigneeEmail())) {
                orderConsigneeDO.setEmail(createReqVO.getConsigneeEmail());
            }
            if (StringUtils.isNotBlank(orderConsigneeDO.getPhone())) {
                orderConsigneeService.save(orderConsigneeDO);
            }
        } else {
            // 控货订单没有收货人则不限制修改收货人
            if (order.getIsCargoControl() && hasConsignee) {
                order.setIsLimitUpdateConsignee(Boolean.TRUE);
            } else {
                order.setIsLimitUpdateConsignee(Boolean.FALSE);
            }
        }
        if (!Objects.equals(createReqVO.getStatus(),
                DRAFT.getValue())) {
            // 发货人 1  收货人 2
            int customerType = this.checkOrderSalesman(order,
                    createReqVO.getOfferId(),
                    null,
                    null,
                    orderConsignorDO,
                    orderConsigneeDO);
            // 更新所属客户经理(业务员)
            if (!DRAFT.getValue().equals(order.getStatus()) && Objects.nonNull(order.getIsChargeCustomer()) && order.getIsChargeCustomer()) {
                addOrderCustomerService(order, customerType);
            }
        }
    }


    public int checkOrderSalesman(OrderDO order, Long offerId, CustomerDO consignorDO, CustomerDO consigneeDO, OrderConsignorDO orderConsignorDO, OrderConsigneeDO orderConsigneeDO) {
        order.setHasConsignee(Objects.nonNull(orderConsigneeDO)); // 订单是否填写了收货人
        int customerType = 1; //1-业绩归属发货人，2-业绩归属收货人
        if (Objects.isNull(orderConsigneeDO)) {//订单收货人
            orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, order.getOrderId()).orderByDesc(OrderConsigneeDO::getId).last("limit 1"));
        }
        if (Objects.isNull(orderConsignorDO)) {//订单发货人
            orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, order.getOrderId()).orderByDesc(OrderConsignorDO::getId).last("limit 1"));
        }
        if (Objects.isNull(consignorDO)) {//发货人客户
            consignorDO = customerService.getCustomer(orderConsignorDO.getCustomerId());
        }
        if (Objects.isNull(consigneeDO) && Objects.nonNull(orderConsigneeDO)) {
            consigneeDO = customerService.getCustomer(orderConsigneeDO.getCustomerId());//收货人客户
        }
        // 原客户经理

        Long orgCustomerId = Objects.isNull(order.getCustomerId()) ? 0L : order.getCustomerId();


        if (Objects.nonNull(order.getType()) && order.getType().contains("2")) {//层级1
            // 海外仓归属发货人
            order.setCustomerId(orderConsignorDO.getCustomerId());
        } else {
            if (consignorDO != null && consignorDO.getNoConsignee() && !order.getHasConsignee()) {//发货人档案设置控货无收货人且订单无收获人，归属发货人业绩 -- 层级2
                order.setCustomerId(orderConsignorDO.getCustomerId());
            } else {
                if (order.getDrawee() == 1) {//发货人付款
                    if (order.getDrawee() == 1 && offerId != null) {//如果是发货人付款且关联报价单，业绩归属发货人 --层级3 第一个
                        order.setCustomerId(orderConsignorDO.getCustomerId());
                    } else if (order.getDrawee() == 1 && consignorDO.getDefaultPay()) {// 如果是发货人付款且档案设置默认付运费  --层级4 第一个
                        order.setCustomerId(orderConsignorDO.getCustomerId());
                    } else {
                        if (consigneeDO != null) {
                            order.setCustomerId(orderConsigneeDO.getCustomerId());
                            customerType = 2;
                        } else {
                            //没有收货人
                            order.setCustomerId(0L);
                            order.setSalesmanId(0L);
                            order.setDeptId(0L);
                            customerType = 0;
                        }
                    }
                } else if (order.getDrawee() == 2) {//收货人付款   层级5 第一个
                    if (consigneeDO != null) {
                        order.setCustomerId(orderConsigneeDO.getCustomerId());
                        customerType = 2;
                    } else {
                        //没有收货人
                        order.setCustomerId(0L);
                        order.setSalesmanId(0L);
                        order.setDeptId(0L);
                        customerType = 0;
                    }
                } else if (order.getDrawee() == 3) { //自定义付款
                    List<CustomDraweeVO> list = JSONObject.parseArray(order.getCustomDrawee(), CustomDraweeVO.class);
                    if (CollectionUtil.isNotEmpty(list)) {
                        List<CustomDraweeVO> freightList = list.stream().filter(s -> s.getName().equals("freight")).collect(Collectors.toList());
                        List<CustomDraweeVO> clearanceFeeList = list.stream().filter(s -> s.getName().equals("clearanceFee")).collect(Collectors.toList());
                        int freight = freightList.get(0).getValue();//运费
                        int clearanceFee = clearanceFeeList.get(0).getValue();//清关费
                        if (offerId != null && (order.getDrawee() == 3 && freight == 1)) {//层级3 第二个 订单关联报价单 && 自定义付款 且发货人付运费
                            order.setCustomerId(orderConsignorDO.getCustomerId());
                        } else if (offerId != null && (order.getDrawee() == 3 && clearanceFee == 1)) {//层级3 第三个 订单关联报价单 && 自定义付款 且发货人付清关费
                            order.setCustomerId(orderConsignorDO.getCustomerId());
                        } else if (consignorDO.getDefaultPay() && (order.getDrawee() == 3 && freight == 1)) { //层级4 第二个 发货人档案设置默认付运费 且发货人付运费 业绩归属 发货人
                            order.setCustomerId(orderConsignorDO.getCustomerId());
                        } else if (consignorDO.getDefaultPay() && (order.getDrawee() == 3 && clearanceFee == 1)) {// 层级4 第三个 发货人档案设置默认付运费 且发货人付清关费  业绩归属发货人
                            order.setCustomerId(orderConsignorDO.getCustomerId());
                        } else {
                            //去掉层级5、6 ，以上不符合的都归收货人
                            if (consigneeDO != null) {
                                order.setCustomerId(orderConsigneeDO.getCustomerId());
                                customerType = 2;
                            } else {
                                //没有收货人
                                order.setCustomerId(0L);
                                order.setSalesmanId(0L);
                                order.setDeptId(0L);
                                customerType = 0;
                            }
                        }
                    }
                } else {
                    //业绩归收货人
                    if (consigneeDO != null) {
                        order.setCustomerId(orderConsigneeDO.getCustomerId());
                        customerType = 2;
                    } else {
                        //没有收货人
                        order.setCustomerId(0L);
                        order.setSalesmanId(0L);
                        order.setDeptId(0L);
                        customerType = 0;
                    }
                }
            }
        }
        // 订单修改是否变动了归属客户，此字段用来判定订单是否需要重置归属客户经理，下单后归属客户的客户经理是固定的，除非订单归属客户变动，才需要重置客户经理
        order.setIsChargeCustomer(!Objects.equals(order.getCustomerId(), orgCustomerId));
        return customerType;
    }

    private void addOrderCustomerService(OrderDO order,
                                         int customerType) {

        if (Objects.nonNull(order.getParentOrderId()) &&
                order.getParentOrderId() > 0 &&
                !order.getSplitSeparateOrder()) {

            // 拆单子订单,并且未标记为独立订单，则不执行客户经理分配规则，以原单为主
            return;
        }
        // 判断该订单、该客户是否有未分配客户异常，如果有，则这个订单不计算业绩
        List<OrderExceptionDO> orderExceptionDOList =
                orderExceptionService.getOrderExceptionByCustomerId(
                        order.getCustomerId());
        // 获取当前订单的异常
        OrderExceptionDO currentOrderException =
                orderExceptionDOList.stream()
                        .filter(orderExceptionDO -> Objects.equals(
                                orderExceptionDO.getOrderId(),
                                order.getOrderId())).findFirst().orElse(null);

        CustomerDO customerDO = customerService.getById(order.getCustomerId());
        if (Objects.nonNull(customerDO)) {
            order.setIsInOpenSea(customerDO.getIsInOpenSea());
            order.setYejiType(customerDO.getIsNew() ? 1 : 0);
        }
        Long oldCustomerService = null;
        // 老客户经理默认为null
        if (Objects.nonNull(customerDO) &&
                Objects.nonNull(customerDO.getCustomerService())
                && customerDO.getCustomerService() != 0L
                && Objects.nonNull(customerDO.getCustomerServiceAssignedTime())
                && !customerDO.getIsCustomerServiceConfirmed()
                && !customerDO.getIsInOpenSea()) {
            // 如果客户存在，客户经理已分配，有分配时间，但是待确认接收，
            // 也不是公海捞取，那么需要判断该客户之前是否有客户经理，没有则业绩属于公司客户，有则业绩归属于上个客户经理
            CustomerOperateLogDO customerOperateLogDO =
                    customerOperateLogService.getOne(
                            new LambdaQueryWrapper<CustomerOperateLogDO>()
                                    .eq(CustomerOperateLogDO::getCustomerId, customerDO.getId())
                                    .eq(CustomerOperateLogDO::getOperateType, 4) // TODO 暂定操作类型4为分配操作，有遗漏后面补充操作类型即可
                                    .orderByDesc(CustomerOperateLogDO::getId).last("limit 1"));
            if (Objects.nonNull(customerOperateLogDO) &&
                    Objects.nonNull(customerOperateLogDO.getOldCustomerService())
                    && customerOperateLogDO.getOldCustomerService() != 0L) {

                oldCustomerService = customerOperateLogDO.getOldCustomerService();
            }
        }
        // 没有该订单，该客户的未分配客户经理异常
        if (Objects.isNull(currentOrderException)
                && Objects.nonNull(customerDO)
                && Objects.nonNull(customerDO.getCustomerService())
                && customerDO.getCustomerService() != 0L
                && (customerDO.getIsCustomerServiceConfirmed() ||
                (!customerDO.getIsCustomerServiceConfirmed()
                        && Objects.nonNull(oldCustomerService)))) {

            if (Objects.nonNull(oldCustomerService)) {
                // 如果这里的旧客户经理id不为null，说明此客户属于移交新客户经理，
                // 但是新客户经理还未接收，业绩算老客户经理的
                order.setSalesmanId(oldCustomerService);
            } else {
                order.setSalesmanId(customerDO.getCustomerService());
            }
            AdminUserRespDTO adminUserRespDTO =
                    adminUserApi.getUser(order.getSalesmanId());
            if (Objects.nonNull(adminUserRespDTO)) {
                order.setDeptId(adminUserRespDTO.getDeptId());
            }
        } else if (CollectionUtil.isEmpty(orderExceptionDOList) &&
                Objects.nonNull(customerDO)
                && (Objects.isNull(customerDO.getCustomerService()) ||
                (!customerDO.getIsCustomerServiceConfirmed() &&
                        Objects.isNull(oldCustomerService)))) {

            // 如果客户正在移交新客户经理，但是未接收，并且老客户经理不为null，
            // 则不创建客户经理未分配异常
            //web下单，业绩为收货人，不产生未分配客户经理异常
            if (order.getUserId() != null && order.getUserId() > 0 &&
                    customerType == 2) {
                order.setSalesmanId(0L);
                order.setDeptId(0L);
                log.info("web下单，业绩为收货人，不产生未分配客户经理异常 orderNo={}", order.getOrderNo());
            } else {
                // 只有客户的客户经理为空时
                String descZh = "归属客户：%s  客户编号：%s";
                String descEn = "Customer: %s Customer No.: %s";
                // 该客户没有客户经理, 需要生成异常，判断当前客户是发货人还是收货人
                if (customerType == 1) {
                    // 发货人
                    descZh = String.format(descZh, "发货人", customerDO.getNumber());
                    descEn = String.format(descEn, "consignor", customerDO.getNumber());
                } else {
                    // 收货人
                    descZh = String.format(descZh, "收货人", customerDO.getNumber());
                    descEn = String.format(descEn, "consignee", customerDO.getNumber());
                }
                OrderExceptionCreateReqVO orderExceptionCreateReqVO =
                        this.genOrderException(order.getOrderId(),
                                order, null,
                                order.getCustomerId(),
                                OrderExceptionEnum.NOT_CUSTOMER_SERVICE_EXCEPTION,
                                descZh,
                                descEn);
                orderExceptionService.createOrderException(
                        orderExceptionCreateReqVO);

            }
        } else {
            // 该订单存在该客户未分配客户经理异常，或者该客户的客户经理待接收，
            // 则不再生成未分配客户经理异常，且该订单不产生业绩归属
            order.setSalesmanId(0L);
            order.setDeptId(0L);
        }
    }

    private void compareOrderCustomerService(OrderBackVO vo, List<ApplyInfoVO> applyInfoList, int customerType) {
        // TODO 判断该订单、该客户是否有未分配客户异常，如果有，则这个订单不计算业绩
        List<OrderExceptionDO> orderExceptionDOList = orderExceptionService.getOrderExceptionByCustomerId(vo.getCustomerId());
        // 获取当前订单的异常
        OrderExceptionDO currentOrderException = orderExceptionDOList.stream()
                .filter(orderExceptionDO -> Objects.equals(orderExceptionDO.getOrderId(), vo.getOrderId())).findFirst().orElse(null);
        CustomerDO customerDO = customerService.getById(vo.getCustomerId());
        vo.setIsInOpenSea(Objects.isNull(customerDO) || Objects.isNull(customerDO.getIsInOpenSea()) ? false : customerDO.getIsInOpenSea());
        vo.setYejiType(customerDO.getIsNew() ? 1 : 0);
        // 没有该订单，该客户的未分配客户经理异常
        ApplyInfoVO infoVO = null;
        if (Objects.isNull(currentOrderException) && Objects.nonNull(customerDO) && Objects.nonNull(customerDO.getCustomerService()) && customerDO.getIsCustomerServiceConfirmed()) {
            // 只有客户的客户经理被接收了才算有效
            AdminUserRespDTO orgAdminUserRespDTO = adminUserApi.getUser(vo.getSalesmanId());
            AdminUserRespDTO newAdminUserRespDTO = adminUserApi.getUser(customerDO.getCustomerService());
            if (!Objects.equals(vo.getSalesmanId(), customerDO.getCustomerService())) {
                infoVO = new ApplyInfoVO();
                infoVO.setName("订单业务经理变动/Change in Order Business Manager");
                infoVO.setOrgValue(Objects.nonNull(orgAdminUserRespDTO) ? orgAdminUserRespDTO.getNickname() : "无");
                infoVO.setNewValue(Objects.nonNull(newAdminUserRespDTO) ? newAdminUserRespDTO.getNickname() : "无");
            }
            vo.setSalesmanId(customerDO.getCustomerService());
            if (Objects.nonNull(newAdminUserRespDTO)) {
                vo.setDeptId(newAdminUserRespDTO.getDeptId());
            }
        } else if (Objects.isNull(currentOrderException) && Objects.nonNull(customerDO) && (Objects.isNull(customerDO.getCustomerService()) || !customerDO.getIsCustomerServiceConfirmed())) {
            // 该订单不产生业绩归属
            // 只有客户的客户经理被接收了才算有效
            infoVO = new ApplyInfoVO();
            AdminUserRespDTO orgAdminUserRespDTO = adminUserApi.getUser(vo.getSalesmanId());
            infoVO.setName("订单业务经理变动/Change in Order Business Manager");
            infoVO.setOrgValue(Objects.nonNull(orgAdminUserRespDTO) ? orgAdminUserRespDTO.getNickname() : "无");
            infoVO.setNewValue("无");
            //web下单，业绩为收货人，不产生未分配客户经理异常
            if (vo.getUserId() != null && customerType == 2) {
                vo.setSalesmanId(0L);
                vo.setDeptId(0L);
                vo.setIsCreateCustomerServiceException(Boolean.FALSE);
                log.info("web下单，业绩为收货人，不产生未分配客户经理异常 orderNo={}", vo.getOrderNo());
            } else {
                vo.setIsCreateCustomerServiceException(Boolean.TRUE);
                // 只有客户的客户经理为空时
                String descZh = "归属客户：%s  客户编号：%s";
                String descEn = "Customer: %s Customer No.: %s";
                // 该客户没有客户经理, 需要生成异常，判断当前客户是发货人还是收货人
                if (customerType == 1) {
                    // 发货人
                    descZh = String.format(descZh, "发货人", customerDO.getNumber());
                    descEn = String.format(descEn, "consignor", customerDO.getNumber());
                } else {
                    // 收货人
                    descZh = String.format(descZh, "收货人", customerDO.getNumber());
                    descEn = String.format(descEn, "consignee", customerDO.getNumber());
                }
                vo.setDescZh(descZh);
                vo.setDescEn(descEn);
            }
        } else {
            // 该订单存在该客户未分配客户经理异常，或者该客户的客户经理待接收，则不再生成未分配客户经理异常，且该订单不产生业绩归属
            vo.setSalesmanId(0L);
            vo.setDeptId(0L);
            // 只有客户的客户经理被接收了才算有效
            AdminUserRespDTO orgAdminUserRespDTO = adminUserApi.getUser(vo.getSalesmanId());
            infoVO = new ApplyInfoVO();
            infoVO.setName("订单业务经理变动/Change in Order Business Manager");
            infoVO.setOrgValue(Objects.nonNull(orgAdminUserRespDTO) ? orgAdminUserRespDTO.getNickname() : "无");
            infoVO.setNewValue("无");
        }
        if (infoVO != null) {
            applyInfoList.add(infoVO);
        }
    }


    private int createOrderNoQuoteException(OrderDO orderDO,
                                            int noQuoteOrAutomaticNoQuote,
                                            OrderItemDO orderItemDO) {
        List<OrderExceptionDO> orderNoQuoteExceptionDOList =
                orderExceptionService.getPendingOrderExceptionByOrderIdAndOrderItemIdAndExceptionKey(orderDO.getOrderId(), orderItemDO.getOrderItemId(), OrderExceptionEnum.ORDER_NO_QUOTE_EXCEPTION.getKey());
        if (orderItemDO.getItemStatus() == -1 && !orderItemDO.getIsProd()) {
            if (CollectionUtil.isEmpty(orderNoQuoteExceptionDOList)) {
                OrderExceptionCreateReqVO orderExceptionCreateReqVO =
                        this.genOrderException(orderDO.getOrderId(),
                                orderDO, orderItemDO, null,
                                OrderExceptionEnum.ORDER_NO_QUOTE_EXCEPTION,
                                String.format("订单【%s】中的商品【%s】未报价", orderDO.getOrderNo(), orderItemDO.getProdTitleZh()), String.format("The goods 【%s】 in the order 【%s】 are not quoted", orderItemDO.getProdTitleEn(), orderDO.getOrderNo()));
                orderExceptionService.createOrderException(orderExceptionCreateReqVO);
            }
            noQuoteOrAutomaticNoQuote = 1;
        } else {
            if (CollectionUtil.isNotEmpty(orderNoQuoteExceptionDOList)) {
                // TODO 当其他业务补充了品名价格后，如果还有待处理的未报价异常，需要同步处理掉
                orderExceptionService.autoProcessException(orderDO.getOrderId(), orderItemDO.getOrderItemId(), OrderExceptionEnum.ORDER_NO_QUOTE_EXCEPTION, "设置价格自动处理", OrderExceptionResult.ORDER_NO_QUOTE_EXCEPTION_RESULT.PROCESSED);
                noQuoteOrAutomaticNoQuote = 2;
            }
        }
        return noQuoteOrAutomaticNoQuote;
    }

    private void createOrderInquiryException(OrderDO orderDO, OrderItemDO orderItemDO, WarehouseInInfoVO warehouseInInfoVO, Integer type) {
        List<OrderExceptionDO> orderInquiryExceptionDOList = orderExceptionService.getPendingOrderExceptionByOrderIdAndOrderItemIdAndExceptionKey(orderDO.getOrderId(), orderItemDO.getOrderItemId(), OrderExceptionEnum.LINE_LOOP_EXCEPTION.getKey());
        // 避免在前面自动处理未报价异常和清关费未报价异常时的回调，优先创建了单询异常，造成并发的重复创建
        if (CollectionUtil.isEmpty(orderInquiryExceptionDOList)) {
            if ((Objects.equals(orderDO.getStatus(), OrderStatusEnum.IN_WAREHOUSE.getValue()) || type == 15) && Objects.nonNull(warehouseInInfoVO)
                    && warehouseInInfoVO.getCartonsNum() > 0 && Objects.nonNull(orderItemDO.getNeedOrderInquiry()) && orderItemDO.getNeedOrderInquiry() == 1
                    && Objects.nonNull(orderItemDO.getIsHandlerOrderInquiryException()) && !orderItemDO.getIsHandlerOrderInquiryException()) {
                // 产生单询异常
                OrderExceptionCreateReqVO orderExceptionCreateReqVO = this.genOrderException(orderDO.getOrderId(), orderDO, orderItemDO,
                        null, OrderExceptionEnum.LINE_LOOP_EXCEPTION, String.format("商品【%s】线路单询异常", orderItemDO.getProdTitleZh()),
                        String.format("Line inquiry exception for product [%s]", orderItemDO.getProdTitleEn()));
                orderExceptionService.createOrderException(orderExceptionCreateReqVO);
                // 标记已产生过单询异常, 并更新到数据库
                orderItemDO.setIsHandlerOrderInquiryException(Boolean.TRUE);
                orderItemMapper.update(null, new LambdaUpdateWrapper<OrderItemDO>().set(OrderItemDO::getIsHandlerOrderInquiryException, true).eq(OrderItemDO::getOrderItemId, orderItemDO.getOrderItemId()));
            }
        }
    }

    private int createClearanceFeeNoQuiteException(OrderDO orderDO, int noQuoteOrAutomaticNoQuote, OrderItemDO orderItemDO) {
        // 查询是否有重量超限异常，如果有则不生成清关费异常
        // TODO 查询是否有重量超限异常和渠道包装重量超限异常，如果有则不生成清关费异常
        List<OrderExceptionDO> goodsOverweightExceptionDOList = orderExceptionService.getPendingOrderExceptionByOrderIdAndOrderItemIdAndExceptionKeys(orderDO.getOrderId(), orderItemDO.getOrderItemId(),
                CollectionUtil.newArrayList(OrderExceptionEnum.GOODS_OVERWEIGHT_EXCEPTION.getKey(), OrderExceptionEnum.LINE_WEIGHT_EXCEPTION.getKey()));
        // 渠道重量超限异常 channel_packaging_overweight_exception
//        List<OrderExceptionDO> channelPackagingOverweightExceptionDOList = orderExceptionService.getPendingOrderExceptionByOrderIdAndOrderItemIdAndExceptionKey(orderDO.getOrderId(), orderItemDO.getOrderItemId(), OrderExceptionEnum.CHANNEL_PACKAGING_OVERWEIGHT_EXCEPTION.getKey());
//        if (CollectionUtil.isEmpty(goodsOverweightExceptionDOList) && CollectionUtil.isEmpty(channelPackagingOverweightExceptionDOList)) {
        if (CollectionUtil.isEmpty(goodsOverweightExceptionDOList) || goodsOverweightExceptionDOList.size() == 0) {
            List<OrderExceptionDO> orderClearanceFeeNoQuoteExceptionDOList = orderExceptionService.getPendingOrderExceptionByOrderIdAndOrderItemIdAndExceptionKey(orderDO.getOrderId(), orderItemDO.getOrderItemId(), OrderExceptionEnum.CUSTOMS_FEE_NOT_QUOTE_EXCEPTION.getKey());
            if (orderItemDO.getCharging() == 0 && (Objects.isNull(orderItemDO.getOriginalClearanceFreight()) || orderItemDO.getOriginalClearanceFreight().compareTo(BigDecimal.ZERO) == 0)
                    && ((Objects.isNull(orderItemDO.getChannelManualPricing()) || !orderItemDO.getChannelManualPricing())
                    && (Objects.isNull(orderItemDO.getSpecialPriceType()) || !orderItemDO.getSpecialPriceType())
                    && (Objects.isNull(orderItemDO.getSplitCustomPriceType()) || !orderItemDO.getSplitCustomPriceType()))) {
                if (CollectionUtil.isEmpty(orderClearanceFeeNoQuoteExceptionDOList)) {
                    // 1-未设置商品清关费, 2-区间未匹配上
                    int productPriceEmptyType = orderItemDO.getProductPriceEmptyType();
                    // 1-未设置渠道清关费, 2-区间未匹配上, 3-包装类型未设置
                    int channelPriceEmptyType = orderItemDO.getChannelPriceEmptyType();
                    // 是否超出空运重量上限
                    boolean isAirWeightLimit = orderItemDO.getIsAirWeightLimit();
                    String descZh = "订单中商品%s的清关费未设置或已过期";
                    String descEn = "The customs clearance fee for item %s in the order has not been set or has expired";
                    if (productPriceEmptyType == 2) {
                        descZh = "订单中商品%s的清关费区间未匹配上";
                        descEn = "The customs clearance fee range for product %s in the order does not match";
                    }
                    descZh = String.format(descZh, orderItemDO.getProdTitleZh());
                    descEn = String.format(descEn, orderItemDO.getProdTitleEn());
                    // 当前空运或海空联运订单下单时，没又渠道id，则生成渠道异常
                    OrderExceptionCreateReqVO orderExceptionCreateReqVO = this.genOrderException(orderDO.getOrderId(), orderDO, orderItemDO, null, OrderExceptionEnum.CUSTOMS_FEE_NOT_QUOTE_EXCEPTION,
                            descZh, descEn);
                    orderExceptionService.createOrderException(orderExceptionCreateReqVO);
                }
                noQuoteOrAutomaticNoQuote = 1;
            } else {
                if (CollectionUtil.isNotEmpty(orderClearanceFeeNoQuoteExceptionDOList)) {
                    // 当其他业务补充了品名空运清关费价格后，如果还有待处理的清关费未报价异常，需要同步处理掉
                    orderExceptionService.autoProcessException(orderDO.getOrderId(), orderItemDO.getOrderItemId(), OrderExceptionEnum.CUSTOMS_FEE_NOT_QUOTE_EXCEPTION, "设置价格自动处理", OrderExceptionResult.CUSTOMS_FEE_NOT_QUOTE_EXCEPTION_RESULT.PROCESSED);
                    noQuoteOrAutomaticNoQuote = 2;
                }
            }
        }
        return noQuoteOrAutomaticNoQuote;
    }


    private void createFeeChangeException(OrderDO orderDO, Integer type, BigDecimal oldFreightAndClearanceFee, BigDecimal newFreightAndClearanceFee) {
        if (type == 10 && oldFreightAndClearanceFee.compareTo(newFreightAndClearanceFee) != 0) {
            // 订单修改业务需要判断收费异常
            // 当订单的运费收费总金额变动时，需要产生异常
            // 当订单修改审批通过后，订单的收费总金额有变动，且当前订单没有多箱异常/少箱异常/重货异常未处理且订单无收费异常，需产生异常
            // 当订单修改审批通过后，订单的收费总金额有变动，且当前订单没有多箱异常/少箱异常/重货异常未处理且订单有收费异常，需更新异常，更新运费金额
            // 处理结果：待处理/已跟客户确认可出/客户不同意发出,只需更新异常处理结果，无需进一步处理
            List<OrderExceptionDO> exceptionDOList = orderExceptionService.getPendingOrderExceptionByOrderIdAndOrderItemIdAndExceptionKeys(orderDO.getOrderId(), null,
                    Arrays.asList(OrderExceptionEnum.ORDER_SUPERFLUOUS_BOX_EXCEPTION.getKey(), OrderExceptionEnum.ORDER_LACK_BOX_EXCEPTION.getKey(), OrderExceptionEnum.ORDER_HEAVY_CARGO_EXCEPTION.getKey(), OrderExceptionEnum.ORDER_BULKY_CARGO_EXCEPTION.getKey()));
            if (CollectionUtil.isEmpty(exceptionDOList)) {
                BigDecimal changeAmount = oldFreightAndClearanceFee.subtract(newFreightAndClearanceFee);
                String descZh = String.format("订单修改审批通过后运费与清关费的总额变%s", (changeAmount.compareTo(BigDecimal.ZERO) > 0 ? "少了" : "多了"));
                String descEn = changeAmount.compareTo(BigDecimal.ZERO) > 0 ? "After the approval of order modification, the total amount of shipping and customs clearance fees has decreased" :
                        "After the order modification approval, the total amount of shipping and customs clearance fees has increased";
                List<OrderExceptionDO> feeExceptionDOList = orderExceptionService.getPendingOrderExceptionByOrderIdAndOrderItemIdAndExceptionKey(orderDO.getOrderId(), null, OrderExceptionEnum.FEE_EXCEPTION.getKey());
                if (CollectionUtil.isEmpty(feeExceptionDOList) && Objects.equals(TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue(), orderDO.getTransportId())) {
                    OrderExceptionCreateReqVO orderExceptionCreateReqVO = this.genOrderException(orderDO.getOrderId(), orderDO, null, null, OrderExceptionEnum.FEE_EXCEPTION, descZh, descEn);
                    orderExceptionService.createOrderException(orderExceptionCreateReqVO);
                } else if (!Objects.equals(TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue(), orderDO.getTransportId())) {
                    if (CollectionUtil.isNotEmpty(feeExceptionDOList)) {
                        // 当订单变为非空运订单时，如果异常未处理，则自动删除异常
                        for (OrderExceptionDO orderExceptionDO : feeExceptionDOList) {
                            orderExceptionService.handlerRemoveFeeExceptionById(orderExceptionDO.getId());
                        }
                    }
                } else {
                    if (Objects.equals(orderDO.getStatus(), OrderStatusEnum.ORDER_PLACED.getValue()) || Objects.equals(orderDO.getStatus(), OrderStatusEnum.WAREHOUSING.getValue())) {
                        // 当订单再次修改审批通过运费清关费变动时，如果异常未处理，则更新异常
                        for (OrderExceptionDO orderExceptionDO : feeExceptionDOList) {
                            OrderExceptionDescVO orderExceptionDescVO = new OrderExceptionDescVO();
                            orderExceptionDescVO.setDescZh(descZh);
                            orderExceptionDescVO.setDescEn(descEn);
                            // 如果不为空，则更新此异常的文案说明
                            orderExceptionService.update(new LambdaUpdateWrapper<OrderExceptionDO>().set(OrderExceptionDO::getOrderExceptionDetails, JSONObject.toJSONString(orderExceptionDescVO)).eq(OrderExceptionDO::getId, orderExceptionDO.getId()));
                        }
                    }
                }
            }

        }
    }

    private void handleException(Long orderId, OrderDO orderDO, int type) {
        OrderConsignorDO orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, orderId).last("limit 1"));
        OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, orderId).last("limit 1"));
        List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderId));
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        String updater = String.valueOf(loginUser != null ? loginUser.getId() : null);
        // 插入订单商品项
        orderBusinessService.costCalculation(updater, orderDO, orderConsignorDO.getCustomerId(), Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerId(),
                orderConsignorDO.getCustomerContactsId(), Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerContactsId(), orderItemDOList, type);
    }

    private void handleException(Long orderId, OrderDO orderDO, List<OrderChangePriceParam> channelPriceParams, int type) {
        OrderConsignorDO orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, orderId).last("limit 1"));
        OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, orderId).last("limit 1"));
        List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderId));
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (CollectionUtil.isNotEmpty(channelPriceParams)) {
            Map<Long, OrderChangePriceParam> channelPriceParamMap = channelPriceParams.stream()
                    .collect(Collectors.toMap(OrderChangePriceParam::getOrderItemId, v -> v, (v1, v2) -> v2));
            for (OrderItemDO it : orderItemDOList) {
                OrderChangePriceParam channelPriceParam = channelPriceParamMap.get(it.getOrderItemId());
                if (Objects.nonNull(channelPriceParam)) {
                    if (it.getCharging() == 0) {
                        // 运费+清关费，两者都为0则不是自定义价格
                        if ((Objects.isNull(channelPriceParam.getFreightFee()) || channelPriceParam.getFreightFee().compareTo(BigDecimal.ZERO) == 0)
                                && (Objects.isNull(channelPriceParam.getClearanceFee()) || channelPriceParam.getClearanceFee().compareTo(BigDecimal.ZERO) == 0)) {
                            continue;
                        }
                    } else {
                        // 全包价 运费不为0即是自定义价格，否则跳过
                        if (Objects.isNull(channelPriceParam.getFreightFee()) || channelPriceParam.getFreightFee().compareTo(BigDecimal.ZERO) == 0) {
                            continue;
                        }
                    }
                    it.setOneSeaFreight(channelPriceParam.getFreightFee());
                    if (it.getCharging() == 0) {
                        it.setOneClearanceFreight(channelPriceParam.getClearanceFee());
                    }
                    it.setChannelManualPricing(true); // 确认渠道/单询手动定价/重量超限异常定价
                }
            }
        }
        String updater = String.valueOf(loginUser != null ? loginUser.getId() : null);
        // 插入订单商品项
        orderBusinessService.costCalculation(updater, orderDO, orderConsignorDO.getCustomerId(), Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerId(),
                orderConsignorDO.getCustomerContactsId(), Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerContactsId(), orderItemDOList, type);
//        orderMapper.updateById(orderDO);
    }


    private OrderExceptionCreateReqVO genOrderException(Long orderId, OrderDO orderDO, OrderItemDO orderItemDO, Long customerId,
                                                        OrderExceptionEnum orderException, String descZh, String descEn) {
        OrderExceptionCreateReqVO orderExceptionCreateReqVO = new OrderExceptionCreateReqVO();
        orderExceptionCreateReqVO.setOrderId(orderId);
        orderExceptionCreateReqVO.setOrderNumber(orderDO.getOrderNo());
        orderExceptionCreateReqVO.setCustomerId(Objects.nonNull(customerId) ? customerId : null);
        if (Objects.nonNull(orderItemDO)) {
            orderExceptionCreateReqVO.setOrderItemId(orderItemDO.getOrderItemId());
        }
        orderExceptionCreateReqVO.setOrderExceptionType(orderException.getKey());
        orderExceptionCreateReqVO.setOrderExceptionDescVO(OrderExceptionDescVO.builder().descZh(descZh).descEn(descEn).build());
        return orderExceptionCreateReqVO;
    }

    private OrderExceptionCreateReqVO genOrderException(Long orderId, OrderBackVO vo, OrderItemDO orderItemDO, Long customerId,
                                                        OrderExceptionEnum orderException, String descZh, String descEn) {
        OrderExceptionCreateReqVO orderExceptionCreateReqVO = new OrderExceptionCreateReqVO();
        orderExceptionCreateReqVO.setOrderId(orderId);
        orderExceptionCreateReqVO.setOrderNumber(vo.getOrderNo());
        orderExceptionCreateReqVO.setCustomerId(Objects.nonNull(customerId) ? customerId : null);
        if (Objects.nonNull(orderItemDO)) {
            orderExceptionCreateReqVO.setOrderItemId(orderItemDO.getOrderItemId());
        }
        orderExceptionCreateReqVO.setOrderExceptionType(orderException.getKey());
        orderExceptionCreateReqVO.setOrderExceptionDescVO(OrderExceptionDescVO.builder().descZh(descZh).descEn(descEn).build());
        return orderExceptionCreateReqVO;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateOrder(OrderUpdateReqVO updateReqVO,
                            MemberUserDO memberUserDO) {

        int type = 2;
        if (Objects.equals(TransportTypeShortEnum.SEA_CONTAINER.getValue(), updateReqVO.getTransportId()) || Objects.equals(TransportTypeShortEnum.MARINE_CONTAINER.getValue(), updateReqVO.getTransportId())) {
            // 非空运订单，对前端传值的空运参数做格式化处理
            updateReqVO.setPortDestCustomsClear(0);
            updateReqVO.setDeliveryWay(0);
            updateReqVO.setDoubleClear(0);
            updateReqVO.setDoubleClear(0);
            updateReqVO.setIsSingleTicketTransport(false);
            updateReqVO.setIsUnpack(false);
            updateReqVO.setCustomsClearCertRemarks("");
            updateReqVO.setCustomsClearCert(false);
            updateReqVO.setAirlineCompany(0L);
        }
        // 获取功能开关
        List<DictDataRespDTO> dictList = dictDataApi.getDictDatas("part_function_switch");
        // 智慧预装功能开关
        DictDataRespDTO dictDataRespDTO = dictList.stream().filter(dto -> "create_order_phone_limit".equals(dto.getLabel())).findFirst().orElse(null);
        if (updateReqVO.getHasConsignee() && Objects.nonNull(updateReqVO.getIsCargoControl()) &&
                updateReqVO.getIsCargoControl() &&
                Objects.nonNull(dictDataRespDTO) && StringUtils.equals(dictDataRespDTO.getValue(), "11") && StringUtils.isNotBlank(updateReqVO.getCountryCode()) && StringUtils.equals("86", updateReqVO.getCountryCode())) {
            throw exception(CONSIGNEE_PHONE_IS_EXTERNAL);
        }
        OrderDO updateObj = OrderConvert.INSTANCE.convert(updateReqVO);

        LogisticsInfoDto logisticsInfoDto = warehouseLineMapper.getStartInfoAndDestInfoByLineId(updateReqVO.getLineId());
        if (Objects.isNull(logisticsInfoDto)) {
            throw exception(ORDER_LINE_NOT_EXIST);
        }
        if (!Objects.equals(logisticsInfoDto.getStartCityId(), updateReqVO.getDepartureId()) || !Objects.equals(logisticsInfoDto.getDestCityId(), updateReqVO.getObjectiveId())) {
            throw exception(ORDER_DEPARTURE_OBJECTIVE_AND_LINE_NOT_AGREEMENT);
        }
        if (!Objects.equals(updateReqVO.getTransportId(), logisticsInfoDto.getTransportId())) {
            throw exception(TRANSPORT_AND_LINE_NOT_AGREEMENT);
        }
        if (updateObj.getIsExternalWarehouse() && StringUtils.isNotBlank(updateObj.getType()) && updateObj.getType().contains("1")) {
            throw exception(EXTERNAL_WAREHOUSE_AND_CONCENTRATE_TRANSPORT_NOT_PARALLEL);
        }
        if (updateObj.getIsExternalWarehouse()) {
            // 校验外部仓信息是否为空
            if (CollectionUtil.isEmpty(updateReqVO.getExternalWarehouseDtoList())) {
                throw exception(ORDER_EXTERNAL_WAREHOUSE_NOT_NULL);
            }
        }
        OrderDO oldOrderDO = orderMapper.selectById(updateObj.getOrderId());
        if (Objects.isNull(oldOrderDO)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        if (oldOrderDO.getOrderNo().contains("DRAFT")) {
            // 原单为草稿订单
            updateObj.setIsChargeDraft(true);
        }
        // 避免并发操作导致的订单编号覆盖，因订单编号为后台生成，所以订单编号更新以旧数据和新生成的为准，不使用前端传参参数
        updateObj.setOrderNo(oldOrderDO.getOrderNo());
        boolean isResetOrderNo = Boolean.FALSE;
        if (Objects.equals(updateReqVO.getIsExternalWarehouse(), !oldOrderDO.getIsExternalWarehouse())) {
            isResetOrderNo = Boolean.TRUE;
        }
        // 判断集运订单类型是否有变动
        if ((StringUtils.isNotBlank(oldOrderDO.getType()) && StringUtils.isNotBlank(updateReqVO.getType()) && oldOrderDO.getType().contains("1") && !updateReqVO.getType().contains("1")) ||
                (StringUtils.isNotBlank(oldOrderDO.getType()) && StringUtils.isBlank(updateReqVO.getType()) && oldOrderDO.getType().contains("1")) ||
                (StringUtils.isBlank(oldOrderDO.getType()) && StringUtils.isNotBlank(updateReqVO.getType()) && updateReqVO.getType().contains("1"))) {
            isResetOrderNo = Boolean.TRUE;
        }
        if (null == updateReqVO.getStatus() || !Objects.equals(oldOrderDO.getStatus(), DRAFT.getValue())) {
            updateObj.setStatus(oldOrderDO.getStatus());
        }
        List<OrderItemDO> oldOrderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, oldOrderDO.getOrderId()));
        List<OrderItemDO> orderItemDOList = updateReqVO.getOrderItemVOList().stream().map(OrderItemConvert.INSTANCE::convert).collect(Collectors.toList());
        Map<Long, OrderItemDO> currencyDOMap = orderItemDOList.stream().filter(item -> Objects.nonNull(item.getOrderItemId()) && item.getOrderItemId() != 0)
                .collect(Collectors.toMap(OrderItemDO::getOrderItemId, Function.identity(), (key1, key2) -> key2));
        List<Long> itemIds = oldOrderItemDOList.stream().map(OrderItemDO::getOrderItemId).filter(orderItemId -> Objects.isNull(currencyDOMap.get(orderItemId))).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(itemIds)) {
            // 编辑时有对商品项进行删除
            orderItemMapper.update(null, new LambdaUpdateWrapper<OrderItemDO>().set(OrderItemDO::getDeleted, 1).in(OrderItemDO::getOrderItemId, itemIds));
        }
        if (!Objects.equals(oldOrderDO.getStatus(), DRAFT.getValue()) && !Objects.equals(oldOrderDO.getStatus(), OrderStatusEnum.ORDER_PLACED.getValue()) && !Objects.equals(oldOrderDO.getStatus(), OrderStatusEnum.WAREHOUSING.getValue())) {
            // 不是草稿、已下单、入仓中状态 走审批流程
            throw exception(PLEASE_SUBMIT_ORDER_UPDATE_APPROVAL);
        }
        if (updateObj.getDrawee() == 3) {
            // 自定义付款人
            if (CollectionUtil.isNotEmpty(updateReqVO.getCustomDraweeVOList())) {
                updateObj.setCustomDrawee(JSONObject.toJSONString(updateReqVO.getCustomDraweeVOList()));
            } else {
                throw exception(ORDER_CUSTOM_DRAWEE_INFO_NOT_NULL);
            }
        }
        // 订单始发地信息
        OrderDepartureDO departureDO = orderDepartureService.getOne(new LambdaQueryWrapper<OrderDepartureDO>().eq(OrderDepartureDO::getOrderId, updateObj.getOrderId()).last("limit 1"));
        if (Objects.isNull(departureDO) || !Objects.equals(departureDO.getDepartureId(), updateReqVO.getDepartureId())) {
            // 查询始发地与目的地信息
            RegionDO departure = regionService.getRegion(updateReqVO.getDepartureId());
            if (Objects.isNull(departure) || (!StrUtil.equals(departure.getType(), "2") && !StrUtil.equals(departure.getType(), "3"))) {
                throw exception(DEPARTURE_NOT_EXISTS);
            }
            if (Objects.isNull(departureDO)) {
                departureDO = new OrderDepartureDO();
            }
            departureDO.setDepartureId(updateReqVO.getDepartureId());
            departureDO.setDeparture(JSONObject.toJSONString(departure));
        }
        String oldOrderNo = oldOrderDO.getOrderNo(); // 临时保存旧的订单编号
        boolean isDisassociation = false; // 是否解除关联
        // 订单目的地信息
        OrderObjectiveDO objectiveDO = orderObjectiveService.getOne(new LambdaQueryWrapper<OrderObjectiveDO>().eq(OrderObjectiveDO::getOrderId, updateObj.getOrderId()).last("limit 1"));
        if (Objects.isNull(objectiveDO) || isResetOrderNo || !Objects.equals(objectiveDO.getObjectiveId(), updateReqVO.getObjectiveId()) || oldOrderDO.getOrderNo().contains("DRAFT")) {
            boolean isSaveOrUpdateOrderNo = true;
            // 目的地发生变更,则重新生成订单号, 或状态从草稿变为下单
            RegionDO objective = regionService.getRegion(updateReqVO.getObjectiveId());
            if (Objects.isNull(objectiveDO)) {
                objectiveDO = new OrderObjectiveDO();
            }
            RegionDO oldObjective = JSONObject.parseObject(objectiveDO.getObjective(), RegionDO.class);
            // 如果是空运订单,订单运输方式未变,目的地国家未变，则不用更新订单编号
            if (updateReqVO.getTransportId() == 3 && Objects.equals(updateReqVO.getTransportId(), oldOrderDO.getTransportId()) && !oldOrderDO.getOrderNo().contains("DRAFT")
                    && !Objects.equals(updateReqVO.getStatus(), DRAFT.getValue())) {
                if (Objects.nonNull(objective) && Objects.nonNull(oldObjective)) {
                    String[] labelCodes = objective.getLabelCode().split(StrUtil.DASHED);
                    String[] oldLabelCodes = oldObjective.getLabelCode().split(StrUtil.DASHED);
                    // 空运订单编号国家代码在目的地配置国家简称的第三位
                    if (labelCodes.length > 2 && oldLabelCodes.length > 2 && StringUtils.equals(labelCodes[2], oldLabelCodes[2])) {
                        // 空运订单的国家代码未变动，不需要重新生成
                        isSaveOrUpdateOrderNo = false;
                    }
                }
            }
            if (Objects.equals(objectiveDO.getObjectiveId(), updateReqVO.getObjectiveId()) && updateReqVO.getTransportId() == 3
                    && Objects.equals(updateReqVO.getTransportId(), oldOrderDO.getTransportId()) && !oldOrderDO.getOrderNo().contains("DRAFT")
                    && !Objects.equals(updateReqVO.getStatus(), DRAFT.getValue())) {

                isSaveOrUpdateOrderNo = false;
            }
            objectiveDO.setObjectiveId(updateReqVO.getObjectiveId());
            objectiveDO.setObjective(JSONObject.toJSONString(objective));

            if (isSaveOrUpdateOrderNo) {
                String newOrderNo;
                if (Objects.equals(updateReqVO.getStatus(), DRAFT.getValue())) {
                    newOrderNo = "DRAFT-" + System.currentTimeMillis();
                } else {
                    newOrderNo = orderBusinessService.saveOrUpdateOrderNo(objective, updateReqVO.getTransportId(), updateReqVO.getIsExternalWarehouse(),
                            StringUtils.isNotBlank(updateReqVO.getType()) && updateReqVO.getType().contains("1"));
                    applicationContext.publishEvent(new OfferUpdateOrderNumberEvent(updateObj.getOrderId(), newOrderNo));
                }
                updateObj.setOrderNo(newOrderNo);
                isDisassociation = true;
            }
        } else if (!Objects.equals(updateReqVO.getTransportId(), oldOrderDO.getTransportId())) {
            // 目的地未变，运输方式变更，重新生成订单号
            RegionDO objective = JSONObject.parseObject(objectiveDO.getObjective(), RegionDO.class);
            String newOrderNo;
            if (Objects.equals(updateReqVO.getStatus(), DRAFT.getValue())) {
                newOrderNo = "DRAFT-" + System.currentTimeMillis();
            } else {
                newOrderNo = orderBusinessService.saveOrUpdateOrderNo(objective, updateReqVO.getTransportId(), updateObj.getIsExternalWarehouse(),
                        StringUtils.isNotBlank(updateReqVO.getType()) && updateReqVO.getType().contains("1"));
                applicationContext.publishEvent(new OfferUpdateOrderNumberEvent(updateObj.getOrderId(), newOrderNo));
            }
            updateObj.setOrderNo(newOrderNo);
            isDisassociation = true;
        }

        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        String updater = String.valueOf(loginUser != null ? loginUser.getId() : null);
        Date now = new Date();
        updateObj.setUpdater(updater);
        updateObj.setUpdateTime(now);
        if (Objects.nonNull(updateReqVO.getHarvestMethod()) && updateReqVO.getHarvestMethod() == 2) {
            updateObj.setCountry(updateReqVO.getCountry());
            updateObj.setProvince(updateReqVO.getProvince());
            updateObj.setCity(updateReqVO.getCity());
            updateObj.setConsigneeAddress(updateReqVO.getConsigneeAddress());
        } else {
            updateObj.setCountry(0L);
            updateObj.setProvince(0L);
            updateObj.setCity(0L);
            updateObj.setConsigneeAddress("");
        }
        departureDO.setUpdater(updater);
        departureDO.setUpdateTime(now);
        departureDO.setDepartureCountryId(logisticsInfoDto.getStartCountryId());
        departureDO.setDepartureWarehouseId(logisticsInfoDto.getStartWarehouseId());
        departureDO.setOrderId(updateObj.getOrderId());
        departureDO.setUpdater(updater);
        departureDO.setUpdateTime(now);
        orderDepartureService.saveOrUpdate(departureDO);

        objectiveDO.setUpdater(updater);
        objectiveDO.setUpdateTime(now);
        objectiveDO.setObjectiveCountryId(logisticsInfoDto.getDestCountryId());
        objectiveDO.setObjectiveWarehouseId(logisticsInfoDto.getDestWarehouseId());
        objectiveDO.setOrderId(updateObj.getOrderId());
        objectiveDO.setUpdater(updater);
        objectiveDO.setUpdateTime(now);
        orderObjectiveService.saveOrUpdate(objectiveDO);

        if (Objects.isNull(memberUserDO) || null == updateReqVO.getUserId() || 0L == updateReqVO.getUserId()) {
            // admin添加的订单
            this.adminUpdateConsignorAndConsignee(updateReqVO, updateObj, updater, now, dictDataRespDTO);
        } else {
            // app-web添加的订单
            this.appUpdateConsignorAndConsignee(updateReqVO, updateObj, updater, now, memberUserDO, dictDataRespDTO);
        }
        // 如果渠道为空,或者非空运订单，则默认给0，只在管理端控制层强制校验空运相关业务渠道必填
        if (Objects.isNull(updateObj.getChannelId()) || updateObj.getTransportId() == 1 || updateObj.getTransportId() == 2) {
            updateObj.setChannelId(0L);
        }
        if (!oldOrderNo.contains("DRAFT") && !StringUtils.equals(oldOrderNo, updateObj.getOrderNo())) {
            updateObj.setNoChargeRecord(StringUtils.isNotBlank(oldOrderDO.getNoChargeRecord()) ?
                    (oldOrderDO.getNoChargeRecord() + StrUtil.COMMA + oldOrderNo) : oldOrderNo);
            chargeOrderNo(updateObj, oldOrderNo);
        }
        if (Objects.isNull(updateReqVO.getDisplayBillLadingPrice())) {
            // 查询订单归属客户的默认档案设置
            if (Objects.nonNull(updateObj.getCustomerId()) && updateObj.getCustomerId() > 0L) {
                CustomerDO customerDO = customerService.getById(updateObj.getCustomerId());
                if (Objects.nonNull(customerDO) && Objects.nonNull(customerDO.getIsShowTidanPrice())) {
                    updateObj.setDisplayBillLadingPrice(customerDO.getIsShowTidanPrice());
                    updateObj.setIsInOpenSea(customerDO.getIsInOpenSea());
                    updateObj.setYejiType(customerDO.getIsNew() ? 1 : 0);
                }
            }
        }
        orderMapper.updateById(updateObj);


        // 插入订单商品项
        orderBusinessService.costCalculation(updater, updateObj, updateReqVO.getConsignorId(), Objects.isNull(updateReqVO.getConsigneeId()) ? 0L : updateReqVO.getConsigneeId(),
                updateReqVO.getConsignorContactsId(), Objects.isNull(updateReqVO.getConsigneeContactsId()) ? 0L : updateReqVO.getConsigneeContactsId(), orderItemDOList, type);

        // 如果报价单id不为空，则表示此订单关联报价单
        if (Objects.nonNull(updateReqVO.getOfferId()) && updateReqVO.getOfferId() > 0L) {
            applicationContext.publishEvent(new OfferAssociationOrderEvent(updateReqVO.getOfferId(), updateObj.getOrderId(), updateObj.getOrderNo(), updater));
        }
        // 更新特需
        this.saveOrUpdateSpecialNeed(updateObj.getOrderId(), updateObj.getPackageType(), updateObj.getPackageRemarks(), updater, now);
        // 修改订单时如果状态为下单,且原订单状态不是下单，更新日志事件
        if (Objects.equals(OrderStatusEnum.ORDER_PLACED.getValue(), updateObj.getStatus()) && !Objects.equals(oldOrderDO.getStatus(), updateObj.getStatus())) {
            if (Objects.equals(TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue(), updateObj.getTransportId())) {
                orderBusinessService.addAirOrderTimeLog(updateObj, OrderAirTimeEnum.AIR_ORDER_PLACED, null, null, null, null, now, null);
            } else if (Objects.equals(TransportTypeShortEnum.SEA_CONTAINER.getValue(), updateObj.getTransportId())) {
                orderBusinessService.addSeaOrderTimeLog(updateObj, OrderSeaTimeEnum.SEA_ORDER_PLACED, null, null, null, null, now, null);
            } else {
                orderBusinessService.addOrderTimeLog(updateObj.getStatus(), updateObj, 0, now, now);
            }
            //草稿状态编辑后下单，需要更新客户状态
            Set<Long> idSet = Stream.of(updateReqVO.getConsignorId(), updateReqVO.getConsigneeId(), updateReqVO.getCustomerId()).filter(Objects::nonNull).collect(Collectors.toSet());
            for (Long id : idSet) {
                OrderDO orderDO = orderMapper.selectById(updateReqVO.getOrderId());
                customerService.updateCustomerByCreateOrder(id, updateReqVO.getOrderId(), orderDO != null ? orderDO.getOrderNo() : "", new Date());
            }
        }
        // 空运相关订单处理业务
        if (Objects.equals(OrderStatusEnum.ORDER_PLACED.getValue(), updateObj.getStatus())) {
            if (Objects.equals(TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue(), updateReqVO.getTransportId())
                    || Objects.equals(TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue(), updateReqVO.getTransportId())) {
                // 空运渠道异常处理，当编辑订单后，订单渠道补充完，则调用处理空运渠道异常
                if ((Objects.isNull(oldOrderDO.getChannelId()) || oldOrderDO.getChannelId() == 0L) && Objects.nonNull(updateObj.getChannelId()) && updateObj.getChannelId() > 0) {
                    orderExceptionService.orderChannelExceptionCallback(oldOrderDO.getOrderId());
                }
                if (Objects.isNull(updateObj.getChannelId()) || 0 == updateObj.getChannelId()) {
                    // 当前空运或海空联运订单下单时，没有渠道id，则生成渠道异常
                    OrderExceptionCreateReqVO orderExceptionCreateReqVO = this.genOrderException(updateObj.getOrderId(), updateObj, null, null, OrderExceptionEnum.CHANNEL_EXCEPTION,
                            "未选择线路渠道", "No route channel selected");
                    orderExceptionService.createOrderException(orderExceptionCreateReqVO);
                }
            } else {
                // 非空运则自动处理掉待处理得渠道异常
                orderExceptionService.orderChannelExceptionCallback(oldOrderDO.getOrderId());
            }
        }
        if (isDisassociation) {
            orderGuanlianService.deleteRelationByOrderId(updateReqVO.getOrderId());
        }
        // 更新订单操作日志
        orderBusinessService.addOrderOperateLog(updateObj.getOrderId(),
                "编辑订单", null);

        //修改，在创建完订单号，计算订单业绩类型
        Long orderId = updateReqVO.getOrderId();
        CalculateOrderYeJiTypeEvent even = new CalculateOrderYeJiTypeEvent();
        even.setOrderId(orderId);
        applicationContext.publishEvent(even);
        //end 在创建完订单号，计算订单业绩类型

        //入仓完成，计算V值
        /*27号注释
        CalculateOrderVValueEvent event=new CalculateOrderVValueEvent();
        event.setOrderId(updateObj.getOrderId());
        applicationContext.publishEvent(event);
        */

        //end 入仓完成，计算V值

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderApply(OrderUpdateReqVO updateReqVO, MemberUserDO memberUserDO) {
        OrderBackVO vo = orderQueryService.getOrder(updateReqVO.getOrderId());
        if (Objects.isNull(vo)) {
            throw exception(ORDER_NOT_EXISTS);
        }
//        if (Objects.nonNull(vo.getParentOrderId()) && vo.getParentOrderId() > 0 && !vo.getSplitSeparateOrder()) {
//            // 如果是拆单订单，且未标记为独立订单，则不允许修改
//            throw exception(SPLIT_ORDER_REVOKE_CAN_UPDATE);
//        }
        OrderApprovalDO orderApprovalDO = orderApprovalMapper.newItemInfo(null, vo.getOrderId(), ORDER_UPDATE.getValue());
        if (Objects.nonNull(orderApprovalDO) && orderApprovalDO.getStatus() == 1) {
            throw exception(YOUR_APPLY_PENDING);
        }
        if (Objects.equals(vo.getStatus(), DRAFT.getValue())
                || Objects.equals(vo.getStatus(), OrderStatusEnum.ORDER_PLACED.getValue()) || Objects.equals(vo.getStatus(), OrderStatusEnum.WAREHOUSING.getValue())) {
            // 是草稿、已下单、入仓中状态 直接修改
            this.updateOrder(updateReqVO, memberUserDO);

            return;
        }
        OrderApprovalTypeCheckEvent approvalTypeCheckEvent = new OrderApprovalTypeCheckEvent(vo.getOrderId(), null, ORDER_UPDATE.getValue(), null, false);
        applicationContext.publishEvent(approvalTypeCheckEvent);
        if (approvalTypeCheckEvent.getResult()) {
            throw exception(ORDER_IS_APPROVAL_IN_PROCESS);
        }
        if (vo.getShipmentState() > 0) {
            throw exception(ORDER_SHIPMENT_NOT_UPDATE);
        }
        // 获取功能开关
        List<DictDataRespDTO> dictList = dictDataApi.getDictDatas("part_function_switch");
        // 智慧预装功能开关
        DictDataRespDTO dictDataRespDTO = dictList.stream().filter(dto -> "create_order_phone_limit".equals(dto.getLabel())).findFirst().orElse(null);
        // 此处只允许修改订单商品项的货值
        long count = updateReqVO.getOrderItemVOList().stream().filter(it -> Objects.isNull(it.getOrderItemId())).count();
        if (count > 0) {
            // 订单项修改审批，不允许添加新的商品项
            throw exception(MODIFY_APPROVAL_NOT_ADD_PROD);
        }
        // 校验参数运输方式、始发地、目的地、线路是否匹配
        LogisticsInfoDto logisticsInfoDto = warehouseLineMapper.getStartInfoAndDestInfoByLineId(updateReqVO.getLineId());
        if (Objects.isNull(logisticsInfoDto)) {
            throw exception(ORDER_LINE_NOT_EXIST);
        }
        if (!Objects.equals(logisticsInfoDto.getStartCityId(), updateReqVO.getDepartureId()) || !Objects.equals(logisticsInfoDto.getDestCityId(), updateReqVO.getObjectiveId())) {
            throw exception(ORDER_DEPARTURE_OBJECTIVE_AND_LINE_NOT_AGREEMENT);
        }
        if (!Objects.equals(updateReqVO.getTransportId(), logisticsInfoDto.getTransportId())) {
            throw exception(TRANSPORT_AND_LINE_NOT_AGREEMENT);
        }
        // 执行订单审批申请业务
        this.orderAuditApplyUpdate(updateReqVO, vo, logisticsInfoDto, dictDataRespDTO, false);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void shipmentOrderApplyUpdate(OrderUpdateReqVO updateReqVO, MemberUserDO memberUserDO) {
        OrderBackVO vo = orderQueryService.getOrder(updateReqVO.getOrderId());
        if (Objects.isNull(vo)) {
            throw exception(ORDER_NOT_EXISTS);
        }
//        if (Objects.nonNull(vo.getParentOrderId()) && vo.getParentOrderId() > 0 && !vo.getSplitSeparateOrder()) {
//            // 如果是拆单订单，且未标记为独立订单，则不允许修改
//            throw exception(SPLIT_ORDER_REVOKE_CAN_UPDATE);
//        }
        OrderApprovalDO orderApprovalDO = orderApprovalMapper.newItemInfo(null, vo.getOrderId(), ORDER_UPDATE.getValue());
        if (Objects.nonNull(orderApprovalDO) && orderApprovalDO.getStatus() == 1) {
            throw exception(YOUR_APPLY_PENDING);
        }
        if (Objects.equals(vo.getStatus(), DRAFT.getValue())
                || Objects.equals(vo.getStatus(), OrderStatusEnum.ORDER_PLACED.getValue()) || Objects.equals(vo.getStatus(), OrderStatusEnum.WAREHOUSING.getValue())) {
            // 是草稿、已下单、入仓中状态 直接修改
            this.updateOrder(updateReqVO, memberUserDO);
            return;
        }

        if (Objects.equals(vo.getStatus(), OrderStatusEnum.IN_WAREHOUSE.getValue())) {
            // 已入仓业务
            this.updateOrderApply(updateReqVO, memberUserDO);
            return;
        }
        OrderApprovalTypeCheckEvent approvalTypeCheckEvent = new OrderApprovalTypeCheckEvent(vo.getOrderId(), null, ORDER_UPDATE.getValue(), null, false);
        applicationContext.publishEvent(approvalTypeCheckEvent);
        if (approvalTypeCheckEvent.getResult()) {
            throw exception(ORDER_IS_APPROVAL_IN_PROCESS);
        }
        // 获取功能开关
        List<DictDataRespDTO> dictList = dictDataApi.getDictDatas("part_function_switch");
        // 智慧预装功能开关
        DictDataRespDTO dictDataRespDTO = dictList.stream().filter(dto -> "create_order_phone_limit".equals(dto.getLabel())).findFirst().orElse(null);
        // 此处只允许修改订单商品项的货值
        long count = updateReqVO.getOrderItemVOList().stream().filter(it -> Objects.isNull(it.getOrderItemId())).count();
        if (count > 0) {
            // 订单修改审批，不允许添加新的商品项
            throw exception(MODIFY_APPROVAL_NOT_ADD_PROD);
        }
        /**
         *  海运订单预装未装柜/空运订单分拣未出货
         * ----跟现有的不便，锁定订单信息无法修改
         * l 海运订单、拆单子单已装柜/空运已出货.
         * A. 运输方式，始发城市，目的国字段锁定不允许修改
         * B. 海外仓选择不允许修改，需要通过申请记录来变更
         * C. 是否控货字段，当是否控货从是修改成否，需校验订单是否有放货记录状态≠已取消，有则弹出提示“订单已放货，无法修改为不控货”；
         *      当是否控货从否修改成是，校验订单是否有提货记录，有则弹出提示“订单已有提货记录，无法修改成控货”
         * D. 当订单所在自编号已起运，无法修改报关方式
         * E. 订单信息修改，需校验订单对应提单是否已审批通过，是需弹出提示“提单已制作，如需修改请联系客服”，仅做提示确认后允许提交，审批通过后需要同步更新自编号中订单信息。
         * F. 订单修改通过后，插入的操作日志中需要注明当前的订单状态，如在航运中修改，在日志中备注订单状态：航运中
         * 注：海运+拆单子单已装柜/空运+拆单子单已出货修改订单信息需单独按钮，支持权限配置，与现有的订单编辑按钮不共用；
         * 订单修改审批流程跟现有的订单审批流程一致，订单信息修改后无需产生异常，不判断异常条件是否满足
         * 海运订单、拆单子单已装柜/空运已出货，订单信息修改，不需要更新价格
         */
        // 海运订单预装未装柜/空运订单分拣未出货, 锁定订单信息无法修改
        if (vo.getShipmentState() == 0 || vo.getShipmentState() == 305 || vo.getShipmentState() == 307 || vo.getShipmentState() == 407) {
            if (vo.getTransportId() == TransportTypeShortEnum.SEA_CONTAINER.getValue()) {
                throw exception(ORDER_PRE_INSTALLATION_UNPACKAGED_CONTAINER_NOT_UPDATE);
            } else {
                // 当前不是海运就是空运
                throw exception(ORDER_SORTING_NOT_SHIPMENT_NOT_UPDATE);
            }
        }
        // 不允许修改运输方式
        if (updateReqVO.getTransportId() != vo.getTransportId()) {
            throw exception(NOT_UPDATE_TRANSPORT);
        }
        LogisticsInfoDto logisticsInfoDto = warehouseLineMapper.getStartInfoAndDestInfoByLineId(updateReqVO.getLineId());
        LogisticsInfoDto orgLogisticsInfoDto = warehouseLineMapper.getStartInfoAndDestInfoByLineId(vo.getLineId());
        // 不允许修改始发地
        if (!Objects.equals(logisticsInfoDto.getStartCityId(), updateReqVO.getDepartureId())) {
            throw exception(NOT_UPDATE_DEPARTURE);
        }
        // 不允许修改目的国
        if (!Objects.equals(logisticsInfoDto.getDestCountryId(), orgLogisticsInfoDto.getDestCountryId())) {
            throw exception(NOT_UPDATE_DEST_COUNTRY);
        }
        // 海外仓业务变动申请
        if ((!vo.getType().contains("2") && updateReqVO.getType().contains("2")) || (vo.getType().contains("2") && !updateReqVO.getType().contains("2"))) {
            throw exception(ORDER_OVERSEAS_WAREHOUSE_UPDATE_NEED_APPLY);
        }
        // 当是否控货从是修改成否，需校验订单是否有放货记录状态≠已取消，有则弹出提示“订单已放货，无法修改为不控货”
        if (vo.getIsCargoControl() && !updateReqVO.getIsCargoControl()) {
            // TODO 校验订单是否有放货记录
            long pickCount = orderCargoControlPickMapper.selectCount(new LambdaQueryWrapper<OrderCargoControlPickDO>()
                    .eq(OrderCargoControlPickDO::getOrderId, updateReqVO.getOrderId())
                    .in(OrderCargoControlPickDO::getStatus, 1, 2, 3, 4, 5, 6));
            if (pickCount > 0) {
                // 订单存在放货记录，不能取消控货
                throw exception(ORDER_EXISTS_PICK_NOT_CANCEL_CARGO_CONTROL);
            }
        }
        // 当是否控货从否修改成是，校验订单是否有提货记录，有则弹出提示“订单已有提货记录，无法修改成控货”
        if (!vo.getIsCargoControl() && updateReqVO.getIsCargoControl()) {
            // 校验订单是否有提货记录
            long pickupCount = orderPickupMapper.selectCount(new LambdaQueryWrapper<OrderPickupDO>()
                    .eq(OrderPickupDO::getOrderId, vo.getOrderNo()));
            if (pickupCount > 0) {
                // 订单存在提货记录，不能进行控货
                throw exception(ORDER_EXISTS_PICKUP_NOT_CARGO_CONTROL);
            }
        }
        // 执行订单审批申请业务
        this.orderAuditApplyUpdate(updateReqVO, vo, logisticsInfoDto, dictDataRespDTO, true);
    }


    /**
     * 订单修改审批信息封装
     *
     * @param updateReqVO
     * @param vo
     * @param logisticsInfoDto
     */
    private void orderAuditApplyUpdate(OrderUpdateReqVO updateReqVO, OrderBackVO vo, LogisticsInfoDto logisticsInfoDto,
                                       DictDataRespDTO dictDataRespDTO, boolean isShipment) {
        String statusName = "";
        if (isShipment) {
            if (!Objects.equals(vo.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue()) && !Objects.equals(vo.getTransportId(), TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue())) {
                statusName = OrderStatusEnum.valueOf(vo.getStatus()).getNameZh();
            } else {
                if (vo.getStatus().equals(OrderStatusEnum.IN_SHIPPING.getValue())) {
                    // 此状态为状态13的空运转义状态，当运输方式为空运时，状态13为已起飞, 订单日志信息单独更新
                    statusName = OrderStatusEnum.HAS_TAKEN_OFF.getNameZh();
                }
                if (vo.getStatus().equals(OrderStatusEnum.SHIPMENT.getValue()) && vo.getShipmentState().equals(BoxAirStatusEnum.WAREHOUSED)) {
                    // 此状态为状态32的空运转义状态，当运输方式为空运时，状态32为,出货子状态为出仓， 订单实时状态为出仓
                    statusName = OrderStatusEnum.WAREHOUSED.getNameZh();
                }
                if (vo.getStatus().equals(OrderStatusEnum.UNLOADED_CABINET.getValue()) && vo.getShipmentState().equals(BoxAirStatusEnum.TO_WAREHOUSED)) {
                    // 此状态为空运到仓状态
                    statusName = OrderStatusEnum.WAREHOUSED.getNameZh();
                }
            }
        }
        OrderApprovalDO orderApprovalDO;
        OrderDO updateObj = OrderConvert.INSTANCE.convert(updateReqVO);
        if (updateReqVO.getIsExternalWarehouse() && StringUtils.isNotBlank(updateReqVO.getType()) && updateReqVO.getType().contains("1")) {
            throw exception(EXTERNAL_WAREHOUSE_AND_CONCENTRATE_TRANSPORT_NOT_PARALLEL);
        }
        if (updateReqVO.getIsExternalWarehouse()) {
            // 校验外部仓信息是否为空
            if (CollectionUtil.isEmpty(updateReqVO.getExternalWarehouseDtoList())) {
                throw exception(ORDER_EXTERNAL_WAREHOUSE_NOT_NULL);
            }
        }
        if (updateReqVO.getDrawee() == 3) {
            // 自定义付款人
            if (CollectionUtil.isNotEmpty(updateReqVO.getCustomDraweeVOList())) {
                updateObj.setCustomDrawee(JSONObject.toJSONString(updateReqVO.getCustomDraweeVOList()));
            } else {
                throw exception(ORDER_CUSTOM_DRAWEE_INFO_NOT_NULL);
            }
        }
        // 如果渠道为空,或者非空运订单，则默认给0，只在管理端控制层强制校验空运相关业务渠道必填
        if (Objects.isNull(updateObj.getChannelId()) || updateObj.getTransportId() == 1 || updateObj.getTransportId() == 2) {
            updateReqVO.setChannelId(0L);
        }
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        String updater = String.valueOf(loginUser != null ? loginUser.getId() : null);
        Date now = new Date();

        vo.setCcIds(updateReqVO.getCcIds());
        vo.setApplyType(ORDER_UPDATE.getValue());

        LinkedList<ApplyInfoVO> applyInfoList = new LinkedList<>();
        // 通用信息比较
        this.compareGenericForms(updateReqVO, vo, applyInfoList);
        // 空运信息比较
        if (Objects.equals(updateReqVO.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue()) || Objects.equals(updateReqVO.getTransportId(), TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue())) {
            // 空运需要设置空运相关信息
            this.compareAirInfo(updateReqVO, vo, applyInfoList);
        }
        if ((Objects.equals(vo.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue()) || Objects.equals(vo.getTransportId(), TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue()))
                && (!Objects.equals(updateReqVO.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue()) && !Objects.equals(updateReqVO.getTransportId(), TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue()))) {
            // 原订单是空运，当前改为非空运则要清空空运相关设置信息
            this.compareClearAirInfo(updateReqVO, vo, applyInfoList);
        }
        // 线路信息比较
        this.compareLine(updateReqVO, vo, applyInfoList, logisticsInfoDto);

        // 比较发货人信息
        CustomerContactsDO consignorContactsDO = customerContactsService.getCustomerContacts(updateReqVO.getConsignorContactsId());
        OrderConsignorBackVO orderConsignorBackVO = vo.getConsignorVO();
        CustomerDO consignorDO = null;
        boolean hasConsignee = Objects.nonNull(updateReqVO.getHasConsignee()) ? updateReqVO.getHasConsignee() : true;
        if (Objects.nonNull(consignorContactsDO)) {
            consignorDO = customerService.getById(consignorContactsDO.getCustomerId());
            if (Objects.nonNull(consignorDO)) {
                // TODO 非控货订单是否必须有收货人
                if (vo.getIsCargoControl() && vo.getHasConsignee() != hasConsignee) {
                    ApplyInfoVO infoVO = new ApplyInfoVO();
                    infoVO.setName("控货订单是否有无收货人");
                    infoVO.setOrgValue(vo.getHasConsignee() ? "有" : "无");
                    infoVO.setNewValue(hasConsignee ? "有" : "无");
                    vo.setHasConsignee(hasConsignee);
                    applyInfoList.add(infoVO);
                    // 发货人控货无收货人属性设置变动，需要变动客户业绩
                    vo.setIsCharge(true);
                }
                orderConsignorBackVO.setCustomerNumber(consignorDO.getNumber());
            }
            this.compareConsignorInfo(updateReqVO, consignorContactsDO, orderConsignorBackVO, applyInfoList, vo);
        }
        vo.setConsignorVO(orderConsignorBackVO);
        // 比较收货人信息
        CustomerContactsDO consigneeContactsDO = customerContactsService.getCustomerContacts(updateReqVO.getConsigneeContactsId());
        OrderConsigneeBackVO orderConsigneeBackVO = vo.getConsigneeVO();
        CustomerDO consigneeDO = customerService.getById(updateReqVO.getConsigneeId());
        if (Objects.nonNull(consigneeDO)) {
            if (Objects.isNull(orderConsigneeBackVO)){
                orderConsigneeBackVO = new OrderConsigneeBackVO();
                // 会走这里，说明订单从无收货人改为有收货人
                orderConsigneeBackVO.setIsCharge(true);
            }
            orderConsigneeBackVO.setCustomerNumber(consigneeDO.getNumber());
        }
//        if (vo.getIsCargoControl() && hasConsignee) {
        if (hasConsignee) {
            if (Objects.isNull(consigneeContactsDO)) {
                //todo 需要判断手机号唯一性，判断规则：1.区号相同，2.先判断手机号码是否存在，然后再判断：a.如果是0开头，判断是否存在非0开头号码；b.如果非0开头，判断是否存在0开头号码
//            consigneeDO = customerService.getById(updateReqVO.getConsignorId());
                // 客户不存在，新增客户联系人信息 orderConsigneeDO中有值
                // 20230511 收货人无客户档案时 判断发货人有无客户经理，没有 生成客户档案，进入待分配。
                // 有客户经理，则暂时不生成客户档案。(放在入仓时处理）
                if (consigneeDO == null || consigneeDO.getCustomerService() == null || consigneeDO.getCustomerService() == 0) {
                    consigneeContactsDO = customerService.createConsigeeCustomer(
                            orderConsigneeBackVO.getName(),
                            orderConsigneeBackVO.getCountryCode(),
                            orderConsigneeBackVO.getPhone(),
                            orderConsigneeBackVO.getCompany(),
                            orderConsigneeBackVO.getEmail(),
                            consigneeDO, vo.getOrderNo());
                }
            }
            if (Objects.nonNull(consigneeContactsDO)) {
                this.compareConsigneeInfo(updateReqVO, consigneeContactsDO, orderConsigneeBackVO, applyInfoList, vo, dictDataRespDTO);
            }
        } else {
            // 控货订单发货人设置为控货无收货人，这里需要处理掉订单的收货人信息
            if (Objects.nonNull(orderConsigneeBackVO) && !hasConsignee) {
                ApplyInfoVO infoVO = new ApplyInfoVO();
                infoVO.setName("控货订单发货人设置为控货无收货人，清除订单收货人信息/Set the shipper of the controlled goods order to no consignee, and clear the consignee information of the order");
                applyInfoList.add(infoVO);
                vo.setIsChargeNoConsignee(true);
            }
        }
        if (vo.getIsCharge() || orderConsignorBackVO.getIsCharge() ||
                orderConsigneeBackVO.getIsCharge()) {
            // TODO  收发货人有变动，则可能业绩归属有变动, 此变动不放入审批详情，
            // 是根据收发货人的变动来实时调整业绩归属
            // 获取最早入仓时间，当入仓时间大于三天，则不允许再修改当前客户归属
            OrderWarehouseInDO warehouseInDO = orderWarehouseInMapper.selectOne(new LambdaQueryWrapper<OrderWarehouseInDO>()
                    .eq(OrderWarehouseInDO::getOrderId, vo.getOrderId())
                    .orderByAsc(OrderWarehouseInDO::getInTime).last("limit 1"));
            if (Objects.isNull(warehouseInDO)) {
                throw exception(ORDER_NOT_WAREHOUSE_IN);
            }
            Date expireTime = DateUtil.offsetDay(warehouseInDO.getInTime(), 3);
            if (expireTime.compareTo(new Date()) >= 0) {
                this.comparePerformanceAttribution(vo, applyInfoList, orderConsignorBackVO, orderConsigneeBackVO, consignorDO, consigneeDO);
            } else {
                ApplyInfoVO infoVO = new ApplyInfoVO();
                infoVO.setName("入仓时间超过三天，订单的业绩归属客户不再变动/If the warehouse entry time exceeds three days, the performance of the order will no longer be attributed to the customer");
                applyInfoList.add(infoVO);
            }
        }
        Map<Long, BigDecimal> itemWorthMap = updateReqVO.getOrderItemVOList().stream().collect(Collectors.groupingBy(OrderItemCreateReqVO::getOrderItemId, Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0).getWorth())));
        OrderDO orderDO = orderMapper.selectById(vo.getOrderId());
        List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, vo.getOrderId()));
        List<ApplyInfoVO> worthApplyInfoList = new ArrayList<>();
        for (OrderItemDO orderItemDO : orderItemDOList) {
            if (Objects.nonNull(itemWorthMap.get(orderItemDO.getOrderItemId()))) {
                if (orderItemDO.getWorth().compareTo(itemWorthMap.get(orderItemDO.getOrderItemId())) != 0) {
                    // 记录货值变动日志
                    ApplyInfoVO applyInfoVO = new ApplyInfoVO();
                    applyInfoVO.setName(orderItemDO.getProdTitleZh() + "的货值");
                    applyInfoVO.setOrgValue(orderItemDO.getWorth().toString());
                    applyInfoVO.setNewValue(itemWorthMap.get(orderItemDO.getOrderItemId()).toString());
                    // 货值变动
                    orderItemDO.setWorth(itemWorthMap.get(orderItemDO.getOrderItemId()));
                    worthApplyInfoList.add(applyInfoVO);

                }
            }
        }
        // 快递单号、特需、特需备注无需审批直接更新
        orderDO.setNumber(updateObj.getNumber());
        orderDO.setPackageRemarks(updateObj.getPackageRemarks());
        orderDO.setPackageType(updateObj.getPackageType());
        // TODO 这里计算费用还是走的之前订单信息参数业务，如果有错误提示，那么捕获错误，允许提交审批
        try {
            orderBusinessService.costCalculation(updater, orderDO, orderConsignorBackVO.getCustomerId(), Objects.isNull(orderConsigneeBackVO) ? 0L : orderConsigneeBackVO.getCustomerId(), orderConsignorBackVO.getCustomerContactsId(), Objects.isNull(orderConsigneeBackVO) ? 0L : orderConsigneeBackVO.getCustomerContactsId(),
                    orderItemDOList, 8);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        if (Objects.nonNull(updateReqVO.getDisplayBillLadingPrice()) && updateReqVO.getDisplayBillLadingPrice() != orderDO.getDisplayBillLadingPrice()) {
            // 是否显示提单价格的设置变动，添加变动日志
            // 记录货值变动日志
            ApplyInfoVO applyInfoVO = new ApplyInfoVO();
            applyInfoVO.setName("提单是否显示价格");
            applyInfoVO.setOrgValue(orderDO.getDisplayBillLadingPrice() ? "显示" : "不显示");
            applyInfoVO.setNewValue(updateReqVO.getDisplayBillLadingPrice() ? "显示" : "不显示");

            orderDO.setDisplayBillLadingPrice(updateReqVO.getDisplayBillLadingPrice());
            vo.setDisplayBillLadingPrice(updateReqVO.getDisplayBillLadingPrice());
            this.update(new LambdaUpdateWrapper<OrderDO>()
                    .set(OrderDO::getDisplayBillLadingPrice, updateReqVO.getDisplayBillLadingPrice())
                    .eq(OrderDO::getOrderId, orderDO.getOrderId()));
            // 订单货值有变动，记录日志
            orderBusinessService.addOrderOperateLog(orderDO.getOrderId(), "订单操作", "提单是否显示价格修改", Collections.singletonList(applyInfoVO));
        }

        // 更新特需
        this.saveOrUpdateSpecialNeed(updateObj.getOrderId(), updateObj.getPackageType(), updateObj.getPackageRemarks(), updater, now);
        if (CollectionUtil.isNotEmpty(worthApplyInfoList)) {
            // 订单货值有变动，记录日志
            orderBusinessService.addOrderOperateLog(orderDO.getOrderId(), "订单操作", "订单货值修改", worthApplyInfoList);
        }
        // 处理完订单相关的所有业务后，如果有待审批的订单修改内容，则创建待审批任务
        if (CollectionUtil.isNotEmpty(applyInfoList)) {
            if (!isShipment) {
                // 2024-09-11 重新修正，出货阶段有单独的修改审批业务需要走
                // 订单修改审批提交不允许在出货阶段进行
                if (vo.getStatus() > 10 && vo.getStatus() < 19) {
                    throw exception(ORDER_UPDATE_APPROVAL_MUST_BE_WAREHOUSE_IN);
                }
            }
            if (isShipment) {
                //  出货阶段的修改，需要将当前订单状态值标出，放首位
                ApplyInfoVO applyInfoVO = new ApplyInfoVO();
                applyInfoVO.setName(statusName);
                applyInfoList.addFirst(applyInfoVO);
            }
            // 订单有修改则执行修改审批任务
            vo.setApplyInfoList(applyInfoList);
            orderApprovalDO = new OrderApprovalDO();
            orderApprovalDO.setOrderId(vo.getOrderId());
            orderApprovalDO.setType(ORDER_UPDATE.getValue());
            orderApprovalDO.setFollowUpSalesmanId(String.valueOf(vo.getSalesmanId()));//跟进业务员为订单的跟进业务员
            vo.setApplyStatus(1);
            vo.setApplyType(ORDER_UPDATE.getValue());
            orderApprovalDO.setStatus(1);
            orderApprovalDO.setDetails(JSONObject.toJSONString(vo));
            orderApprovalDO.setCreator(updater);
            orderApprovalDO.setCreator(updater);
            orderApprovalDO.setUpdater(updater);
            orderApprovalDO.setCreateTime(now);
            orderApprovalDO.setUpdateTime(now);
            orderApprovalMapper.insert(orderApprovalDO);
            String formId = bpmCreateServiceFactory.createBmp(Long.valueOf(updater), orderApprovalDO.getOrderApprovalId(), WorkFlowEmus.ORDER_ORDER_MODIFY.getKey(), vo.getOrderNo(), StringUtils.isNotBlank(vo.getCcIds()) ? vo.getCcIds().split(StrUtil.COMMA) : null);
            vo.setFormId(formId);
            vo.setOrderApprovalId(orderApprovalDO.getOrderApprovalId());
            orderApprovalDO.setDetails(JSONObject.toJSONString(vo));
            orderApprovalDO.setFormId(formId);
            orderApprovalMapper.updateById(orderApprovalDO);

            this.updateStatus(vo.getOrderId(), null, null, null, null, null, 14, OrderApprovalTypeResultEnum.order_update_processing.getDesc(), null, null, JSONObject.toJSONString(applyInfoList));

        }
    }

    private void compareClearAirInfo(OrderUpdateReqVO updateReqVO, OrderBackVO
            vo, List<ApplyInfoVO> applyInfoList) {
        ApplyInfoVO infoVO;
        // 目的港清关
        if (Objects.nonNull(vo.getPortDestCustomsClear()) && vo.getPortDestCustomsClear() != 0) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("目的港清关/Customs clearance at destination port");
            infoVO.setOrgValue(vo.getPortDestCustomsClear() == 1 ? "我司" : "客户");
            infoVO.setNewValue("空");

            vo.setPortDestCustomsClear(0);
            applyInfoList.add(infoVO);
        }
        // 发货方式
        if (Objects.nonNull(vo.getDeliveryWay()) && vo.getDeliveryWay() != 0) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("发货方式/Delivery");
            infoVO.setOrgValue(vo.getDeliveryWay() == 1 ? "多票" : "单票");
            infoVO.setNewValue("空");

            vo.setDeliveryWay(0);
            applyInfoList.add(infoVO);
        }
        // 是否双清
        if (Objects.nonNull(vo.getDoubleClear()) && vo.getDoubleClear() != 0) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("是否双清/Is it double clear");
            infoVO.setOrgValue(vo.getDoubleClear() == 1 ? "客户自清" : "我司双清");
            infoVO.setNewValue("空");

            vo.setDoubleClear(0);
            applyInfoList.add(infoVO);
        }

        // 航空公司
        if (Objects.nonNull(vo.getAirlineCompany()) && vo.getAirlineCompany() != 0L) {
            SupplierDO supplierDO = supplierService.getSupplier(vo.getAirlineCompany());
            if (Objects.nonNull(supplierDO)) {
                infoVO = new ApplyInfoVO();
                infoVO.setName("航空公司/airline company");
                infoVO.setOrgValue(supplierDO.getCompanyZh());
                infoVO.setNewValue("空");

                vo.setAirlineCompany(0L);
                applyInfoList.add(infoVO);
            }
        }
        // 清关证书
        if (!Objects.equals(vo.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue()) && Objects.equals(vo.getTransportId(), TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue())) {
            // 原运输方式不是空运相关时，因为调用的更新方法自动过滤了设置为null的值，所以这里默认的值是false，需要手动转null再去做判断
            vo.setCustomsClearCert(null);
        }
        if ((Objects.nonNull(vo.getCustomsClearCert()))) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("清关证书/Customs clearance certificate");
            infoVO.setOrgValue(vo.getCustomsClearCert() ? "是" : "否");
            infoVO.setNewValue("空");
            // 因为调用的更新方法自动过滤了设置为null的值，所以这里默认给false
            vo.setCustomsClearCert(false);
            applyInfoList.add(infoVO);
        }
        // 清关证书备注
        if ((StringUtils.isNotBlank(vo.getCustomsClearCertRemarks()))) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("清关证书备注/Remarks on customs clearance certificate");
            infoVO.setOrgValue(vo.getCustomsClearCertRemarks());
            infoVO.setNewValue("空");
            // 因为调用的更新方法自动过滤了设置为null的值，所以这里默认给空字符串
            vo.setCustomsClearCertRemarks("");
            applyInfoList.add(infoVO);
        }
        // 是否拆包
        if (!Objects.equals(vo.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue()) && Objects.equals(vo.getTransportId(), TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue())) {
            // 原运输方式不是空运相关时，因为调用的更新方法自动过滤了设置为null的值，所以这里默认的值是false，需要手动转null再去做判断
            vo.setIsUnpack(null);
        }
        if ((Objects.nonNull(vo.getIsUnpack()))) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("是否拆包/Unpacking or not");
            infoVO.setOrgValue(vo.getIsUnpack() ? "是" : "否");
            infoVO.setNewValue("空");
            // 因为调用的更新方法自动过滤了设置为null的值，所以这里默认给false
            vo.setIsUnpack(false);
            applyInfoList.add(infoVO);
        }
        // 是否单票立刻转运  (注：若只有一件，货到仓库立即发，选“是”，多件需仓库集运待发，选“否”)
        if (!Objects.equals(vo.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue()) && Objects.equals(vo.getTransportId(), TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue())) {
            // 原运输方式不是空运相关时，因为调用的更新方法自动过滤了设置为null的值，所以这里默认的值是false，需要手动转null再去做判断
            vo.setIsSingleTicketTransport(null);
        }
        if ((Objects.nonNull(vo.getIsSingleTicketTransport()))) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("单票立刻转运/Single ticket immediate transfer");
            infoVO.setOrgValue(vo.getIsSingleTicketTransport() ? "是" : "否");
            infoVO.setNewValue("空");
            // 因为调用的更新方法自动过滤了设置为null的值，所以这里默认给false
            vo.setIsSingleTicketTransport(false);
            applyInfoList.add(infoVO);
        }
    }

    private void compareAirInfo(OrderUpdateReqVO updateReqVO, OrderBackVO vo, List<ApplyInfoVO> applyInfoList) {
        ApplyInfoVO infoVO;

        // 目的港清关
        if ((Objects.nonNull(vo.getPortDestCustomsClear()) && Objects.isNull(updateReqVO.getPortDestCustomsClear())) ||
                (Objects.isNull(vo.getPortDestCustomsClear()) && Objects.nonNull(updateReqVO.getPortDestCustomsClear())) ||
                !Objects.equals(vo.getPortDestCustomsClear(), updateReqVO.getPortDestCustomsClear())) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("目的港清关/Customs clearance at destination port");
            infoVO.setOrgValue(Objects.isNull(vo.getPortDestCustomsClear()) || vo.getPortDestCustomsClear() == 0 ? "空" : (vo.getPortDestCustomsClear() == 1 ? "我司" : "客户"));
            infoVO.setNewValue(Objects.isNull(updateReqVO.getPortDestCustomsClear()) || updateReqVO.getPortDestCustomsClear() == 0 ? "空" : (updateReqVO.getPortDestCustomsClear() == 1 ? "我司" : "客户"));

            vo.setPortDestCustomsClear(updateReqVO.getPortDestCustomsClear());
            applyInfoList.add(infoVO);
        }
        // 发货方式
        if ((Objects.nonNull(vo.getDeliveryWay()) && Objects.isNull(updateReqVO.getDeliveryWay())) ||
                (Objects.isNull(vo.getDeliveryWay()) && Objects.nonNull(updateReqVO.getDeliveryWay())) ||
                !Objects.equals(vo.getDeliveryWay(), updateReqVO.getDeliveryWay())) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("发货方式/Delivery");
            infoVO.setOrgValue(Objects.isNull(vo.getDeliveryWay()) || vo.getDeliveryWay() == 0 ? "空" : (vo.getDeliveryWay() == 1 ? "多票" : "单票"));
            infoVO.setNewValue(Objects.isNull(updateReqVO.getDeliveryWay()) || updateReqVO.getDeliveryWay() == 0 ? "空" : (updateReqVO.getDeliveryWay() == 1 ? "多票" : "单票"));

            vo.setDeliveryWay(updateReqVO.getDeliveryWay());
            applyInfoList.add(infoVO);
        }
        // 是否双清
        if ((Objects.nonNull(vo.getDoubleClear()) && Objects.isNull(updateReqVO.getDoubleClear())) ||
                (Objects.isNull(vo.getDoubleClear()) && Objects.nonNull(updateReqVO.getDoubleClear())) ||
                !Objects.equals(vo.getDoubleClear(), updateReqVO.getDoubleClear())) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("是否双清/Is it double clear");
            infoVO.setOrgValue(Objects.isNull(vo.getDoubleClear()) || vo.getDoubleClear() == 0 ? "空" : (vo.getDoubleClear() == 1 ? "客户自清" : "我司双清"));
            infoVO.setNewValue(Objects.isNull(updateReqVO.getDoubleClear()) || updateReqVO.getDoubleClear() == 0 ? "空" : (updateReqVO.getDoubleClear() == 1 ? "客户自清" : "我司双清"));

            vo.setDoubleClear(updateReqVO.getDoubleClear());
            applyInfoList.add(infoVO);
        }
        // 航空公司
        if ((Objects.nonNull(vo.getAirlineCompany()) && Objects.isNull(updateReqVO.getAirlineCompany())) ||
                (Objects.isNull(vo.getAirlineCompany()) && Objects.nonNull(updateReqVO.getAirlineCompany())) ||
                !Objects.equals(vo.getAirlineCompany(), updateReqVO.getAirlineCompany())) {
            SupplierDO orgSupplierDO = supplierService.getSupplier(vo.getAirlineCompany());
            SupplierDO newSupplierDO = supplierService.getSupplier(updateReqVO.getAirlineCompany());
            infoVO = new ApplyInfoVO();
            infoVO.setName("航空公司/airline company");
            infoVO.setOrgValue(Objects.nonNull(orgSupplierDO) ? orgSupplierDO.getCompanyZh() : "无");
            infoVO.setNewValue(Objects.nonNull(newSupplierDO) ? newSupplierDO.getCompanyZh() : "无");

            vo.setAirlineCompany(Objects.nonNull(updateReqVO.getAirlineCompany()) ? updateReqVO.getAirlineCompany() : 0L);
            applyInfoList.add(infoVO);
        }
        // 清关证书
        if (!Objects.equals(vo.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue()) && Objects.equals(vo.getTransportId(), TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue())) {
            // 原运输方式不是空运相关时，因为调用的更新方法自动过滤了设置为null的值，所以这里默认的值是false，需要手动转null再去做判断
            vo.setCustomsClearCert(null);
        }
        if ((Objects.nonNull(vo.getCustomsClearCert()) && Objects.isNull(updateReqVO.getCustomsClearCert())) ||
                (Objects.isNull(vo.getCustomsClearCert()) && Objects.nonNull(updateReqVO.getCustomsClearCert())) ||
                !Objects.equals(vo.getCustomsClearCert(), updateReqVO.getCustomsClearCert())) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("清关证书/Customs clearance certificate");
            infoVO.setOrgValue(Objects.isNull(vo.getCustomsClearCert()) ? "空" : (vo.getCustomsClearCert() ? "是" : "否"));
            infoVO.setNewValue(Objects.isNull(updateReqVO.getCustomsClearCert()) ? "空" : (updateReqVO.getCustomsClearCert() ? "是" : "否"));
            // 因为调用的更新方法自动过滤了设置为null的值，所以这里默认给false
            vo.setCustomsClearCert(Objects.nonNull(updateReqVO.getCustomsClearCert()) && updateReqVO.getCustomsClearCert());
            applyInfoList.add(infoVO);
        }
        // 清关证书备注
        if ((StringUtils.isNotBlank(vo.getCustomsClearCertRemarks()) && StringUtils.isBlank(updateReqVO.getCustomsClearCertRemarks())) ||
                (StringUtils.isBlank(vo.getCustomsClearCertRemarks()) && StringUtils.isNotBlank(updateReqVO.getCustomsClearCertRemarks())) ||
                !StringUtils.equals(vo.getCustomsClearCertRemarks(), updateReqVO.getCustomsClearCertRemarks())) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("清关证书备注/Remarks on customs clearance certificate");
            infoVO.setOrgValue(StringUtils.isBlank(vo.getCustomsClearCertRemarks()) ? "空" : vo.getCustomsClearCertRemarks());
            infoVO.setNewValue(StringUtils.isBlank(updateReqVO.getCustomsClearCertRemarks()) ? "空" : updateReqVO.getCustomsClearCertRemarks());
            // 因为调用的更新方法自动过滤了设置为null的值，所以这里默认给空字符串
            vo.setCustomsClearCertRemarks(StringUtils.isBlank(updateReqVO.getCustomsClearCertRemarks()) ? "" : updateReqVO.getCustomsClearCertRemarks());
            applyInfoList.add(infoVO);
        }
        // 是否拆包
        if (!Objects.equals(vo.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue()) && Objects.equals(vo.getTransportId(), TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue())) {
            // 原运输方式不是空运相关时，因为调用的更新方法自动过滤了设置为null的值，所以这里默认的值是false，需要手动转null再去做判断
            vo.setIsUnpack(null);
        }
        if ((Objects.nonNull(vo.getIsUnpack()) && Objects.isNull(updateReqVO.getIsUnpack())) ||
                (Objects.isNull(vo.getIsUnpack()) && Objects.nonNull(updateReqVO.getIsUnpack())) ||
                !Objects.equals(vo.getIsUnpack(), updateReqVO.getIsUnpack())) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("是否拆包/Unpacking or not");
            infoVO.setOrgValue(Objects.isNull(vo.getIsUnpack()) ? "空" : (vo.getIsUnpack() ? "是" : "否"));
            infoVO.setNewValue(Objects.isNull(updateReqVO.getIsUnpack()) ? "空" : (updateReqVO.getIsUnpack() ? "是" : "否"));
            // 因为调用的更新方法自动过滤了设置为null的值，所以这里默认给false
            vo.setIsUnpack(Objects.nonNull(updateReqVO.getIsUnpack()) && updateReqVO.getIsUnpack());
            applyInfoList.add(infoVO);
        }
        // 是否单票立刻转运  (注：若只有一件，货到仓库立即发，选“是”，多件需仓库集运待发，选“否”)
        if (!Objects.equals(vo.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue()) && Objects.equals(vo.getTransportId(), TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue())) {
            // 原运输方式不是空运相关时，因为调用的更新方法自动过滤了设置为null的值，所以这里默认的值是false，需要手动转null再去做判断
            vo.setIsSingleTicketTransport(null);
        }
        if ((Objects.nonNull(vo.getIsSingleTicketTransport()) && Objects.isNull(updateReqVO.getIsSingleTicketTransport())) ||
                (Objects.isNull(vo.getIsSingleTicketTransport()) && Objects.nonNull(updateReqVO.getIsSingleTicketTransport())) ||
                !Objects.equals(vo.getIsSingleTicketTransport(), updateReqVO.getIsSingleTicketTransport())) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("单票立刻转运/Single ticket immediate transfer");
            infoVO.setOrgValue(Objects.isNull(vo.getIsSingleTicketTransport()) ? "空" : (vo.getIsSingleTicketTransport() ? "是" : "否"));
            infoVO.setNewValue(Objects.isNull(updateReqVO.getIsSingleTicketTransport()) ? "空" : (updateReqVO.getIsSingleTicketTransport() ? "是" : "否"));
            // 因为调用的更新方法自动过滤了设置为null的值，所以这里默认给false
            vo.setIsSingleTicketTransport(Objects.nonNull(updateReqVO.getIsSingleTicketTransport()) && updateReqVO.getIsSingleTicketTransport());
            applyInfoList.add(infoVO);
        }

    }

    /**
     * 线路变动会影响价格，需要对已有核销业务做业务拦截
     *
     * @param updateReqVO   变更请求参数
     * @param vo            原订单数据
     * @param applyInfoList 变更详情记录
     */
    private void compareLine(OrderUpdateReqVO updateReqVO, OrderBackVO vo, List<ApplyInfoVO> applyInfoList, LogisticsInfoDto logisticsInfoDto) {
        ApplyInfoVO infoVO;
        // 原线路信息
        LogisticsInfoDto orgLogisticsInfoDto = vo.getLogisticsInfoDto();
        // 运输方式
        if (!Objects.equals(vo.getTransportId(), updateReqVO.getTransportId())) {
            // 获取运输方式
            List<DictDataRespDTO> dictList = dictDataApi.getDictDatas("transport_type");
            String orgValue = dictList.stream().filter(dt -> Objects.equals(vo.getTransportId(), Integer.valueOf(dt.getValue()))).map(DictDataRespDTO::getLabel).findFirst().orElse(null);
            String newValue = dictList.stream().filter(dt -> Objects.equals(updateReqVO.getTransportId(), Integer.valueOf(dt.getValue())))
                    .map(DictDataRespDTO::getLabel).findFirst().orElse(null);
            if (Objects.isNull(newValue)) {
                throw exception(TRANSPORT_LINE_NOT_EXISTS);
            }
            // 原线路信息
            infoVO = new ApplyInfoVO();
            infoVO.setName("运输方式/mode of transport");
            infoVO.setOrgValue(Objects.isNull(orgValue) ? "无" : orgValue);
            infoVO.setNewValue(newValue);
            applyInfoList.add(infoVO);
            // 运输方式变动需要重置订单编号
            vo.setIsResetOrderNo(true);
            vo.setIsTransport(true);
            vo.setTransportId(updateReqVO.getTransportId());
        }

        // 始发地
        if (!Objects.equals(vo.getDepartureId(), updateReqVO.getDepartureId())) {
            // 验证该订单是否有核销应收
            receivableService.verificationReceivableIsWriteOff(vo.getOrderId(), null);
            OrderDepartureBackVO orderDepartureVO = vo.getOrderDepartureVO();
            // 原始发城市信息
            RegionDO orgDeparture = JSONObject.parseObject(orderDepartureVO.getDeparture(), RegionDO.class);
            // 新的始发城市信息
            RegionDO newDeparture = regionService.getRegion(updateReqVO.getDepartureId());
            if (Objects.isNull(newDeparture)) {
                throw exception(DEPARTURE_NOT_EXISTS);
            }
            // 原线路信息
            infoVO = new ApplyInfoVO();
            infoVO.setName("始发地/ORIGIN");
            infoVO.setOrgValue(orgDeparture.getTitleZh());
            infoVO.setNewValue(newDeparture.getTitleZh());
            applyInfoList.add(infoVO);
            vo.setDepartureId(updateReqVO.getDepartureId());
            orderDepartureVO.setDepartureId(updateReqVO.getDepartureId());
            orderDepartureVO.setDeparture(JSONObject.toJSONString(newDeparture));
            orderDepartureVO.setDepartureCountryId(logisticsInfoDto.getStartCountryId());
            orderDepartureVO.setDepartureWarehouseId(logisticsInfoDto.getStartWarehouseId());
            vo.setOrderDepartureVO(orderDepartureVO);
        }

        // 目的地
        if (!Objects.equals(vo.getObjectiveId(), updateReqVO.getObjectiveId())) {
            // 验证该订单是否有核销应收
            receivableService.verificationReceivableIsWriteOff(vo.getOrderId(), null);
            OrderObjectiveBackVO orderObjectiveVO = vo.getOrderObjectiveVO();
            // 原目的城市信息
            RegionDO orgObjective = JSONObject.parseObject(orderObjectiveVO.getObjective(), RegionDO.class);
            // 新的目的城市信息
            RegionDO newObjective = regionService.getRegion(updateReqVO.getObjectiveId());
            if (Objects.isNull(newObjective)) {
                throw exception(OBJECTIVE_NOT_EXISTS);
            }
            // 原线路信息
            infoVO = new ApplyInfoVO();
            infoVO.setName("目的地/destination");
            infoVO.setOrgValue(orgObjective.getTitleZh());
            infoVO.setNewValue(newObjective.getTitleZh());
            applyInfoList.add(infoVO);
            vo.setObjectiveId(updateReqVO.getObjectiveId());
            // 运输方式未变的非空运订单，目的地变动需要重置订单编号
            if (vo.getTransportId() != 3 && !vo.getIsTransport()) {
                vo.setIsResetOrderNo(true);
            }
            orderObjectiveVO.setObjectiveId(updateReqVO.getObjectiveId());
            orderObjectiveVO.setObjective(JSONObject.toJSONString(newObjective));
            orderObjectiveVO.setObjectiveCountryId(logisticsInfoDto.getDestCountryId());
            orderObjectiveVO.setObjectiveWarehouseId(logisticsInfoDto.getDestWarehouseId());
            vo.setOrderObjectiveVO(orderObjectiveVO);
        }

        // 线路
        if (!Objects.equals(vo.getLineId(), updateReqVO.getLineId())) {
            // 验证该订单是否有核销应收
            receivableService.verificationReceivableIsWriteOff(vo.getOrderId(), null);
            infoVO = new ApplyInfoVO();
            infoVO.setName("线路/line");
            infoVO.setOrgValue(orgLogisticsInfoDto.getStartTitleZh() + "->>" + orgLogisticsInfoDto.getDestTitleZh());
            infoVO.setNewValue(logisticsInfoDto.getStartTitleZh() + "->>" + logisticsInfoDto.getDestTitleZh());
            applyInfoList.add(infoVO);
            vo.setLineId(updateReqVO.getLineId());
            OrderDepartureBackVO orderDepartureVO = vo.getOrderDepartureVO();
            orderDepartureVO.setDepartureCountryId(logisticsInfoDto.getStartCountryId());
            orderDepartureVO.setDepartureWarehouseId(logisticsInfoDto.getStartWarehouseId());
            vo.setOrderDepartureVO(orderDepartureVO);
            OrderObjectiveBackVO orderObjectiveVO = vo.getOrderObjectiveVO();
            orderObjectiveVO.setObjectiveCountryId(logisticsInfoDto.getDestCountryId());
            orderObjectiveVO.setObjectiveWarehouseId(logisticsInfoDto.getDestWarehouseId());
            vo.setOrderObjectiveVO(orderObjectiveVO);
            if (vo.getTransportId() == 3 && !vo.getIsTransport()) {
                // 运输方式未变动的空运订单，目的地国家属性变动了，需要重置订单编号
                if (!Objects.equals(orgLogisticsInfoDto.getDestCountryId(), logisticsInfoDto.getDestCountryId())) {
                    vo.setIsResetOrderNo(true);
                }
            }
            // 线路变动肯定要重新计价
            vo.setIsResetPrice(true);
        }

        vo.setChannelId(Objects.isNull(vo.getChannelId()) ? 0L : vo.getChannelId());
        updateReqVO.setChannelId(Objects.isNull(updateReqVO.getChannelId()) ? 0L : updateReqVO.getChannelId());
        // 渠道
        if ((!Objects.equals(vo.getChannelId(), updateReqVO.getChannelId()))) {
            QueryChannelInfoEvent orgEvent = new QueryChannelInfoEvent();
            QueryChannelInfoEvent updateEvent = new QueryChannelInfoEvent();
            if (vo.getChannelId() > 0L) {
                orgEvent.setChannelId(vo.getChannelId());
                applicationContext.publishEvent(orgEvent);
            }
            if (updateReqVO.getChannelId() > 0L) {
                updateEvent.setChannelId(updateReqVO.getChannelId());
                applicationContext.publishEvent(updateEvent);
            }
            // 验证该订单是否有核销应收
            receivableService.verificationReceivableIsWriteOff(vo.getOrderId(), null);
            infoVO = new ApplyInfoVO();
            infoVO.setName("渠道/channel");
            infoVO.setOrgValue(Objects.nonNull(vo.getChannelId()) && vo.getChannelId() > 0L ? orgEvent.getNameZh() : "无");
            infoVO.setNewValue(Objects.nonNull(updateEvent.getChannelId()) && updateEvent.getChannelId() > 0L ? updateEvent.getNameZh() : "无");
            applyInfoList.add(infoVO);
            vo.setChannelId(updateReqVO.getChannelId());
            // 线路变动肯定要重新计价
            vo.setIsResetPrice(true);
        }
    }

    private void compareConsignorInfo(OrderUpdateReqVO updateReqVO, CustomerContactsDO consignorContactsDO,
                                      OrderConsignorBackVO orderConsignorBackVO, List<ApplyInfoVO> applyInfoList, OrderBackVO vo) {

        // 验证该订单是否有核销应收
        receivableService.verificationReceivableIsWriteOff(vo.getOrderId(), null);
        ApplyInfoVO infoVO;
        // 发货人姓名(中文)
        if ((StringUtils.isNotBlank(orderConsignorBackVO.getName()) || StringUtils.isNotBlank(updateReqVO.getConsignorName()))
                && ((StringUtils.isNotBlank(orderConsignorBackVO.getName()) && StringUtils.isBlank(updateReqVO.getConsignorName()))
                || (StringUtils.isBlank(orderConsignorBackVO.getName()) && StringUtils.isNotBlank(updateReqVO.getConsignorName()))
                || !StringUtils.equals(orderConsignorBackVO.getName(), updateReqVO.getConsignorName()))) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("发货人姓名(中文)/Shipper name(Chinese)");
            infoVO.setOrgValue(StringUtils.isNotBlank(orderConsignorBackVO.getName()) ? orderConsignorBackVO.getName() : "空");
            infoVO.setNewValue(StringUtils.isNotBlank(updateReqVO.getConsignorName()) ? updateReqVO.getConsignorName() : "空");
            orderConsignorBackVO.setName(updateReqVO.getConsignorName());
            applyInfoList.add(infoVO);
        }
        // 发货人姓名(英文)
        if ((StringUtils.isNotBlank(orderConsignorBackVO.getNameEn()) || StringUtils.isNotBlank(updateReqVO.getConsignorNameEn()))
                && ((StringUtils.isNotBlank(orderConsignorBackVO.getNameEn()) && StringUtils.isBlank(updateReqVO.getConsignorNameEn()))
                || (StringUtils.isBlank(orderConsignorBackVO.getNameEn()) && StringUtils.isNotBlank(updateReqVO.getConsignorNameEn()))
                || !StringUtils.equals(orderConsignorBackVO.getNameEn(), updateReqVO.getConsignorNameEn()))) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("发货人姓名(英文)/Shipper name(English)");
            infoVO.setOrgValue(StringUtils.isNotBlank(orderConsignorBackVO.getNameEn()) ? orderConsignorBackVO.getNameEn() : "空");
            infoVO.setNewValue(StringUtils.isNotBlank(updateReqVO.getConsignorNameEn()) ? updateReqVO.getConsignorNameEn() : "空");
            orderConsignorBackVO.setNameEn(updateReqVO.getConsignorNameEn());
            applyInfoList.add(infoVO);
        }

        if ((StringUtils.isNotBlank(orderConsignorBackVO.getCompany()) || StringUtils.isNotBlank(updateReqVO.getConsignorCompany()))
                && ((StringUtils.isNotBlank(orderConsignorBackVO.getCompany()) && StringUtils.isBlank(updateReqVO.getConsignorCompany()))
                || (StringUtils.isBlank(orderConsignorBackVO.getCompany()) && StringUtils.isNotBlank(updateReqVO.getConsignorCompany()))
                || !StringUtils.equals(orderConsignorBackVO.getCompany(), updateReqVO.getConsignorCompany()))) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("发货人公司(中文)/Shipper Company (Chinese)");
            infoVO.setOrgValue(StringUtils.isNotBlank(orderConsignorBackVO.getCompany()) ? orderConsignorBackVO.getCompany() : "空");
            infoVO.setNewValue(StringUtils.isNotBlank(updateReqVO.getConsignorCompany()) ? updateReqVO.getConsignorCompany() : "空");
            orderConsignorBackVO.setCompany(StringUtils.isNotBlank(updateReqVO.getConsignorCompany()) ? updateReqVO.getConsignorCompany() : "");
            applyInfoList.add(infoVO);
        }
        if ((StringUtils.isNotBlank(orderConsignorBackVO.getCompanyEn()) || StringUtils.isNotBlank(updateReqVO.getConsignorCompanyEn()))
                && ((StringUtils.isNotBlank(orderConsignorBackVO.getCompanyEn()) && StringUtils.isBlank(updateReqVO.getConsignorCompanyEn()))
                || (StringUtils.isBlank(orderConsignorBackVO.getCompanyEn()) && StringUtils.isNotBlank(updateReqVO.getConsignorCompanyEn()))
                || !StringUtils.equals(orderConsignorBackVO.getCompanyEn(), updateReqVO.getConsignorCompanyEn()))) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("发货人公司(英文)/Shipper Company (English)");
            infoVO.setOrgValue(StringUtils.isNotBlank(orderConsignorBackVO.getCompanyEn()) ? orderConsignorBackVO.getCompanyEn() : "空");
            infoVO.setNewValue(StringUtils.isNotBlank(updateReqVO.getConsignorCompanyEn()) ? updateReqVO.getConsignorCompanyEn() : "空");
            orderConsignorBackVO.setCompanyEn(StringUtils.isNotBlank(updateReqVO.getConsignorCompanyEn()) ? updateReqVO.getConsignorCompanyEn() : "");
            applyInfoList.add(infoVO);
        }
        if ((StringUtils.isNotBlank(orderConsignorBackVO.getEmail()) || StringUtils.isNotBlank(updateReqVO.getConsignorEmail())) && ((StringUtils.isNotBlank(orderConsignorBackVO.getEmail()) && StringUtils.isBlank(updateReqVO.getConsignorEmail())) || (StringUtils.isBlank(orderConsignorBackVO.getEmail()) && StringUtils.isNotBlank(updateReqVO.getConsignorEmail())) || !StringUtils.equals(orderConsignorBackVO.getEmail(), updateReqVO.getConsignorEmail()))) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("发货人邮箱/Shipper's email");
            infoVO.setOrgValue(StringUtils.isNotBlank(orderConsignorBackVO.getEmail()) ? orderConsignorBackVO.getEmail() : "空");
            infoVO.setNewValue(StringUtils.isNotBlank(updateReqVO.getConsignorEmail()) ? updateReqVO.getConsignorEmail() : "空");
            orderConsignorBackVO.setEmail(StringUtils.isNotBlank(updateReqVO.getConsignorEmail()) ? updateReqVO.getConsignorEmail() : "");
            applyInfoList.add(infoVO);
        }
        // 发货人信息
        if (!Objects.equals(orderConsignorBackVO.getCustomerContactsId(), consignorContactsDO.getId())) {
            // 发货人电话
            if (!StringUtils.equals(orderConsignorBackVO.getPhone(), consignorContactsDO.getPhoneNew()) || !StringUtils.equals(orderConsignorBackVO.getCountryCode(), consignorContactsDO.getAreaCode())) {
                infoVO = new ApplyInfoVO();
                infoVO.setName("发货人电话/Shipper's phone number");
                infoVO.setOrgValue("+" + orderConsignorBackVO.getCountryCode() + orderConsignorBackVO.getPhone());
                infoVO.setNewValue("+" + consignorContactsDO.getAreaCode() + consignorContactsDO.getPhoneNew());
                orderConsignorBackVO.setCountryCode(consignorContactsDO.getAreaCode());
                orderConsignorBackVO.setPhone(consignorContactsDO.getPhoneNew());
                applyInfoList.add(infoVO);
            }
            orderConsignorBackVO.setCustomerContactsId(consignorContactsDO.getId());
            orderConsignorBackVO.setCustomerId(consignorContactsDO.getCustomerId());
            // 发货人信息有变动
            orderConsignorBackVO.setIsCharge(true);
            // 重新定价
            // 重新定价
            vo.setIsResetPrice(true);
            vo.setConsignorVO(orderConsignorBackVO);
        }

    }

    private void compareConsigneeInfo(OrderUpdateReqVO updateReqVO, CustomerContactsDO consigneeContactsDO,
                                      OrderConsigneeBackVO orderConsigneeBackVO, List<ApplyInfoVO> applyInfoList,
                                      OrderBackVO vo, DictDataRespDTO dictDataRespDTO) {
        // 验证该订单是否有核销应收
        receivableService.verificationReceivableIsWriteOff(vo.getOrderId(), null);
        ApplyInfoVO infoVO;
        // 收货人姓名(中文)
        if ((StringUtils.isNotBlank(orderConsigneeBackVO.getName()) || StringUtils.isNotBlank(updateReqVO.getConsigneeName()))
                && ((StringUtils.isNotBlank(orderConsigneeBackVO.getName()) && StringUtils.isBlank(updateReqVO.getConsigneeName()))
                || (StringUtils.isBlank(orderConsigneeBackVO.getName()) && StringUtils.isNotBlank(updateReqVO.getConsigneeName()))
                || !StringUtils.equals(orderConsigneeBackVO.getName(), updateReqVO.getConsigneeName()))) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("收货人姓名(中文)/Name of consignee (Chinese)");
            infoVO.setOrgValue(StringUtils.isNotBlank(orderConsigneeBackVO.getName()) ? orderConsigneeBackVO.getName() : "空");
            infoVO.setNewValue(StringUtils.isNotBlank(updateReqVO.getConsigneeName()) ? updateReqVO.getConsigneeName() : "空");
            orderConsigneeBackVO.setName(updateReqVO.getConsigneeName());
            applyInfoList.add(infoVO);
        }
        // 收货人姓名(英文)
        if ((StringUtils.isNotBlank(orderConsigneeBackVO.getNameEn()) || StringUtils.isNotBlank(updateReqVO.getConsigneeNameEn()))
                && ((StringUtils.isNotBlank(orderConsigneeBackVO.getNameEn()) && StringUtils.isBlank(updateReqVO.getConsigneeNameEn()))
                || (StringUtils.isBlank(orderConsigneeBackVO.getNameEn()) && StringUtils.isNotBlank(updateReqVO.getConsigneeNameEn()))
                || !StringUtils.equals(orderConsigneeBackVO.getNameEn(), updateReqVO.getConsigneeNameEn()))) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("收货人姓名(英文)/Name of consignee (English)");
            infoVO.setOrgValue(StringUtils.isNotBlank(orderConsigneeBackVO.getNameEn()) ? orderConsigneeBackVO.getNameEn() : "空");
            infoVO.setNewValue(StringUtils.isNotBlank(updateReqVO.getConsigneeNameEn()) ? updateReqVO.getConsigneeNameEn() : "空");
            orderConsigneeBackVO.setNameEn(updateReqVO.getConsigneeNameEn());
            applyInfoList.add(infoVO);
        }
        if ((StringUtils.isNotBlank(orderConsigneeBackVO.getCompany()) || StringUtils.isNotBlank(updateReqVO.getConsigneeCompany()))
                && ((StringUtils.isNotBlank(orderConsigneeBackVO.getCompany()) && StringUtils.isBlank(updateReqVO.getConsigneeCompany()))
                || (StringUtils.isBlank(orderConsigneeBackVO.getCompany()) && StringUtils.isNotBlank(updateReqVO.getConsigneeCompany()))
                || !StringUtils.equals(orderConsigneeBackVO.getCompany(), updateReqVO.getConsigneeCompany()))) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("收货人公司(中文)/Consignee Company (Chinese)");
            infoVO.setOrgValue(StringUtils.isNotBlank(orderConsigneeBackVO.getCompany()) ? orderConsigneeBackVO.getCompany() : "空");
            infoVO.setNewValue(StringUtils.isNotBlank(updateReqVO.getConsigneeCompany()) ? updateReqVO.getConsigneeCompany() : "空");
            orderConsigneeBackVO.setCompany(StringUtils.isNotBlank(updateReqVO.getConsigneeCompany()) ? updateReqVO.getConsigneeCompany() : "");
            applyInfoList.add(infoVO);
        }
        if ((StringUtils.isNotBlank(orderConsigneeBackVO.getCompanyEn()) || StringUtils.isNotBlank(updateReqVO.getConsigneeCompanyEn()))
                && ((StringUtils.isNotBlank(orderConsigneeBackVO.getCompanyEn()) && StringUtils.isBlank(updateReqVO.getConsigneeCompanyEn()))
                || (StringUtils.isBlank(orderConsigneeBackVO.getCompanyEn()) && StringUtils.isNotBlank(updateReqVO.getConsigneeCompanyEn()))
                || !StringUtils.equals(orderConsigneeBackVO.getCompanyEn(), updateReqVO.getConsigneeCompanyEn()))) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("收货人公司(英文)/Consignee Company (English)");
            infoVO.setOrgValue(StringUtils.isNotBlank(orderConsigneeBackVO.getCompanyEn()) ? orderConsigneeBackVO.getCompanyEn() : "空");
            infoVO.setNewValue(StringUtils.isNotBlank(updateReqVO.getConsigneeCompanyEn()) ? updateReqVO.getConsigneeCompanyEn() : "空");
            orderConsigneeBackVO.setCompanyEn(StringUtils.isNotBlank(updateReqVO.getConsigneeCompanyEn()) ? updateReqVO.getConsigneeCompanyEn() : "");
            applyInfoList.add(infoVO);
        }
        if ((StringUtils.isNotBlank(orderConsigneeBackVO.getEmail()) || StringUtils.isNotBlank(updateReqVO.getConsigneeEmail())) && ((StringUtils.isNotBlank(orderConsigneeBackVO.getEmail()) && StringUtils.isBlank(updateReqVO.getConsigneeEmail())) || (StringUtils.isBlank(orderConsigneeBackVO.getEmail()) && StringUtils.isNotBlank(updateReqVO.getConsigneeEmail())) || !StringUtils.equals(orderConsigneeBackVO.getEmail(), updateReqVO.getConsigneeEmail()))) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("收货人邮箱/Recipient email");
            infoVO.setOrgValue(StringUtils.isNotBlank(orderConsigneeBackVO.getEmail()) ? orderConsigneeBackVO.getEmail() : "空");
            infoVO.setNewValue(StringUtils.isNotBlank(updateReqVO.getConsigneeEmail()) ? updateReqVO.getConsigneeEmail() : "空");
            orderConsigneeBackVO.setEmail(StringUtils.isNotBlank(updateReqVO.getConsigneeEmail()) ? updateReqVO.getConsigneeEmail() : "");
            applyInfoList.add(infoVO);
        }
        if (!Objects.equals(orderConsigneeBackVO.getCustomerContactsId(), consigneeContactsDO.getId())) {
            // 收货人电话
            if (!StringUtils.equals(orderConsigneeBackVO.getPhone(), consigneeContactsDO.getPhoneNew()) || !StringUtils.equals(orderConsigneeBackVO.getCountryCode(), consigneeContactsDO.getAreaCode())) {
                if (updateReqVO.getHasConsignee() && Objects.nonNull(updateReqVO.getIsCargoControl()) && updateReqVO.getIsCargoControl() && StringUtils.isNotBlank(consigneeContactsDO.getAreaCode()) &&
                        Objects.nonNull(dictDataRespDTO) && StringUtils.equals(dictDataRespDTO.getValue(), "11") && StringUtils.equals("86", consigneeContactsDO.getAreaCode())) {
                    throw exception(CONSIGNEE_PHONE_IS_EXTERNAL);
                }
                infoVO = new ApplyInfoVO();
                infoVO.setName("收货人电话/Consignee's phone number");
                infoVO.setOrgValue("+" + orderConsigneeBackVO.getCountryCode() + orderConsigneeBackVO.getPhone());
                infoVO.setNewValue("+" + consigneeContactsDO.getAreaCode() + consigneeContactsDO.getPhoneNew());
                orderConsigneeBackVO.setCountryCode(consigneeContactsDO.getAreaCode());
                orderConsigneeBackVO.setPhone(consigneeContactsDO.getPhoneNew());
                applyInfoList.add(infoVO);
            }
            orderConsigneeBackVO.setCustomerContactsId(consigneeContactsDO.getId());
            orderConsigneeBackVO.setCustomerId(consigneeContactsDO.getCustomerId());
            // 收货人信息有变动
            orderConsigneeBackVO.setIsCharge(true);
            // 重新定价
            vo.setIsResetPrice(true);
            vo.setConsigneeVO(orderConsigneeBackVO);
        }

    }

    private void comparePerformanceAttribution(@NotNull OrderBackVO vo,
                                               List<ApplyInfoVO> applyInfoList,
                                               OrderConsignorBackVO orderConsignorBackVO,
                                               OrderConsigneeBackVO orderConsigneeBackVO,
                                               CustomerDO consignorDO,
                                               CustomerDO consigneeDO) {

        // 原客户经理
        Long orgCustomerId = Objects.isNull(vo.getCustomerId()) ? 0L : vo.getCustomerId();
        CustomerDO orgCustomerDO = customerService.getCustomer(vo.getCustomerId());

        // TODO 客户归属变动时记录日志
        if (!Objects.equals(vo.getStatus(), DRAFT.getValue())) {
            ApplyInfoVO infoVO = null;
            int customerType = 0; // 无变动 0  发货人 1 收货人 2
            if (StringUtils.isNotBlank(vo.getType()) && vo.getType().contains("2")) {
                if (!Objects.equals(vo.getCustomerId(), orderConsignorBackVO.getCustomerId())) {
                    // 海外仓归属发货人
                    customerType = 1;
                    vo.setCustomerId(orderConsignorBackVO.getCustomerId());
                }
            } else {
                if (consignorDO != null && consignorDO.getNoConsignee() && !vo.getHasConsignee()) {//发货人档案设置控货无收货人且订单无收获人，归属发货人业绩 -- 层级2
                    vo.setCustomerId(orderConsignorBackVO.getCustomerId());
                } else {
                    OrderAssociationOfferInfoEvent event = new OrderAssociationOfferInfoEvent(vo.getOrderId(), null, null);
                    applicationContext.publishEvent(event);
                    if (vo.getDrawee() == 1) {//发货人付款
                        if (vo.getDrawee() == 1 && event.getOfferId() != null) {//如果是发货人付款且关联报价单，业绩归属发货人 --层级3 第一个
                            vo.setCustomerId(orderConsignorBackVO.getCustomerId());
                        } else if (vo.getDrawee() == 1 && consignorDO.getDefaultPay()) {// 如果是发货人付款且档案设置默认付运费  --层级4 第一个
                            vo.setCustomerId(orderConsignorBackVO.getCustomerId());
                        } else {
                            vo.setCustomerId(orderConsigneeBackVO.getCustomerId() != null ? orderConsigneeBackVO.getCustomerId() : 0);
                            customerType = 2;
                        }
                    } else if (vo.getDrawee() == 2) {//收货人付款   层级5 第一个
                        if (consigneeDO != null) {
                            vo.setCustomerId(orderConsigneeBackVO.getCustomerId());
                        } else {
                            //没有收货人
                            vo.setCustomerId(0L);
                            vo.setSalesmanId(0L);
                            vo.setDeptId(0L);
                            customerType = 0;
                        }
                    } else if (vo.getDrawee() == 3) { //自定义付款
                        List<CustomDraweeVO> list = JSONObject.parseArray(vo.getCustomDrawee(), CustomDraweeVO.class);
                        if (CollectionUtil.isNotEmpty(list)) {
                            List<CustomDraweeVO> freightList = list.stream().filter(s -> s.getName().equals("freight")).collect(Collectors.toList());
                            List<CustomDraweeVO> clearanceFeeList = list.stream().filter(s -> s.getName().equals("clearanceFee")).collect(Collectors.toList());
                            int freight = freightList.get(0).getValue();//运费
                            int clearanceFee = clearanceFeeList.get(0).getValue();//清关费
                            if (event.getOfferId() != null && (vo.getDrawee() == 3 && freight == 1)) {//层级3 第二个 订单关联报价单 && 自定义付款 且发货人付运费
                                vo.setCustomerId(orderConsignorBackVO.getCustomerId());
                            } else if (event.getOfferId() != null && (vo.getDrawee() == 3 && clearanceFee == 1)) {//层级3 第三个 订单关联报价单 && 自定义付款 且发货人付清关费
                                vo.setCustomerId(orderConsignorBackVO.getCustomerId());
                            } else if (consignorDO.getDefaultPay() && (vo.getDrawee() == 3 && freight == 1)) { //层级4 第二个 发货人档案设置默认付运费 且发货人付运费 业绩归属 发货人
                                vo.setCustomerId(orderConsignorBackVO.getCustomerId());
                            } else if (consignorDO.getDefaultPay() && (vo.getDrawee() == 3 && clearanceFee == 1)) {// 层级4 第三个 发货人档案设置默认付运费 且发货人付清关费  业绩归属发货人
                                vo.setCustomerId(orderConsignorBackVO.getCustomerId());
                            } else {
                                //去掉层级5、6 ，以上不符合的都归收货人
                                vo.setCustomerId(orderConsigneeBackVO.getCustomerId() != null ? orderConsigneeBackVO.getCustomerId() : 0);
                                customerType = 2;
                            }
                        }
                    } else {
                        //业绩归收货人
                        vo.setCustomerId(orderConsigneeBackVO.getCustomerId() != null ? orderConsigneeBackVO.getCustomerId() : 0);
                        customerType = 2;
                    }
                }
            }
            vo.setCustomerType(customerType);

            // 订单所属客户变更，则需要变更业绩归属
            // 更新所属客户经理(业务员)
//            if ((Objects.nonNull(vo.getCustomerId()) && vo.getCustomerId() > 0L) ||
//                    ((Objects.isNull(vo.getCustomerId()) || vo.getCustomerId() == 0L) && Objects.nonNull(vo.getSalesmanId()) && vo.getSalesmanId() > 0L)) {
            // 订单修改是否变动了归属客户，此字段用来判定订单是否需要重置归属客户经理，下单后归属客户的客户经理是固定的，除非订单归属客户变动，才需要重置客户经理
            vo.setIsChargeCustomer(!Objects.equals(vo.getCustomerId(), orgCustomerId));
            if (!Objects.equals(vo.getCustomerId(), orgCustomerId)) {
                CustomerDO newCustomerDO = customerService.getCustomer(vo.getCustomerId());
                infoVO = new ApplyInfoVO();
                infoVO.setName("订单客户归属变动/Change in customer ownership for orders");
                infoVO.setOrgValue(Objects.nonNull(orgCustomerDO) ? ((StringUtils.isNotBlank(orgCustomerDO.getName()) ? orgCustomerDO.getName() : "无") + "/" + (StringUtils.isNotBlank(orgCustomerDO.getNameEn()) ? orgCustomerDO.getNameEn() : "empty")) : "无/not have");
                infoVO.setNewValue(Objects.nonNull(newCustomerDO) ? ((StringUtils.isNotBlank(newCustomerDO.getName()) ? newCustomerDO.getName() : "无") + "/" + (StringUtils.isNotBlank(newCustomerDO.getNameEn()) ? newCustomerDO.getNameEn() : "empty")) : "无/not have");
                applyInfoList.add(infoVO);
                compareOrderCustomerService(vo, applyInfoList, customerType);
            }
        }
    }

    private void compareGenericForms(OrderUpdateReqVO updateReqVO, OrderBackVO
            vo, List<ApplyInfoVO> applyInfoList) {
        ApplyInfoVO infoVO;
        // 订单服务类型
        if ((StringUtils.isNotBlank(vo.getType()) && StringUtils.isBlank(updateReqVO.getType())) ||
                (StringUtils.isBlank(vo.getType()) && StringUtils.isNotBlank(updateReqVO.getType())) ||
                !Objects.equals(vo.getType(), updateReqVO.getType())) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("订单类型/order type");
            // TODO 类型增加时转换方式需要优化
            infoVO.setOrgValue(StringUtils.isBlank(vo.getType()) ? "无" : (StringUtils.equals(vo.getType(), "1,2") ?
                    "集运服务、海外仓" : (vo.getType().contains("1") ? "集运服务" : "海外仓")));
            infoVO.setNewValue(StringUtils.isBlank(updateReqVO.getType()) ? "无" : (StringUtils.equals(updateReqVO.getType(), "1,2") ?
                    "集运服务、海外仓" : (updateReqVO.getType().contains("1") ? "集运服务" : "海外仓")));
            // 判断集运订单类型是否有变动
            if ((StringUtils.isNotBlank(vo.getType()) && StringUtils.isNotBlank(updateReqVO.getType()) && vo.getType().contains("1") && !updateReqVO.getType().contains("1")) ||
                    (StringUtils.isNotBlank(vo.getType()) && StringUtils.isBlank(updateReqVO.getType()) && vo.getType().contains("1")) ||
                    (StringUtils.isBlank(vo.getType()) && StringUtils.isNotBlank(updateReqVO.getType()) && updateReqVO.getType().contains("1"))) {
                vo.setIsResetOrderNo(Boolean.TRUE);
            }
            vo.setType(updateReqVO.getType());
            applyInfoList.add(infoVO);
        }
        // 唛头
        if (!Objects.equals(vo.getMarks(), updateReqVO.getMarks())) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("唛头/marks");
            infoVO.setOrgValue(vo.getMarks());
            infoVO.setNewValue(updateReqVO.getMarks());
            vo.setMarks(updateReqVO.getMarks());
            applyInfoList.add(infoVO);
        }
        // 是否控货
        if (Objects.equals(vo.getIsCargoControl(), !updateReqVO.getIsCargoControl())) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("是否控货/Control of goods or not");
            infoVO.setOrgValue(vo.getIsCargoControl() ? "是/yes" : "否/no");
            infoVO.setNewValue(updateReqVO.getIsCargoControl() ? "是/yes" : "否/no");
            vo.setIsCargoControl(updateReqVO.getIsCargoControl());
            vo.setIsCheckCoupon(Boolean.TRUE);
            applyInfoList.add(infoVO);
        }
        Map<Integer, CurrencyRespDTO> currencyMap = currencyApi.getAllCurrency();
        CurrencyRespDTO orgCurrencyRespDTO = currencyMap.get(vo.getCollectionProxyCurrency());
        CurrencyRespDTO newCurrencyRespDTO = currencyMap.get(updateReqVO.getCollectionProxyCurrency());

//        String orgCurrencyName = Objects.isNull(orgCurrencyRespDTO) ? "无" : (orgCurrencyRespDTO.getTitleZh() +"/"+ orgCurrencyRespDTO.getTitleEn());
        String orgCurrencyName = Objects.isNull(orgCurrencyRespDTO) ? "无" : orgCurrencyRespDTO.getFuhao();
//        String newCurrencyName = Objects.isNull(newCurrencyRespDTO) ? "无" : (newCurrencyRespDTO.getTitleZh()  +"/"+ newCurrencyRespDTO.getTitleEn());
        String newCurrencyName = Objects.isNull(newCurrencyRespDTO) ? "无" : newCurrencyRespDTO.getFuhao();
        // 代收货款
        if (Objects.equals(vo.getIsCollection(), !updateReqVO.getIsCollection())) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("是否代收货款/Whether to collect payment on behalf of others");
            infoVO.setOrgValue(vo.getIsCollection() ? "是/yes" : "否/no");
            infoVO.setNewValue(updateReqVO.getIsCollection() ? "是/yes" : "否/no");
            applyInfoList.add(infoVO);
            infoVO = new ApplyInfoVO();
            infoVO.setName("代收货款金额/Amount of payment collected on behalf");
            infoVO.setOrgValue(vo.getIsCollection() ? (vo.getCollectionProxy() + " " + orgCurrencyName) : "无");
            infoVO.setNewValue(updateReqVO.getIsCollection() ? (updateReqVO.getCollectionProxy() + " " + newCurrencyName) : "无");
            applyInfoList.add(infoVO);
            vo.setIsCollection(updateReqVO.getIsCollection());
            vo.setCollectionProxy(updateReqVO.getCollectionProxy());
            vo.setCollectionProxyCurrency(updateReqVO.getCollectionProxyCurrency());
        }
        // 代收货款金额变动
        if (vo.getIsCollection() && updateReqVO.getIsCollection() &&
                (updateReqVO.getCollectionProxy().compareTo(vo.getCollectionProxy()) != 0 ||
                        !Objects.equals(updateReqVO.getCollectionProxyCurrency(), vo.getCollectionProxyCurrency()))) {

            infoVO = new ApplyInfoVO();
            infoVO.setName("代收货款金额/Amount of payment collected on behalf");
            infoVO.setOrgValue(vo.getIsCollection() ? (vo.getCollectionProxy() + " " + orgCurrencyName) : "无");
            infoVO.setNewValue(updateReqVO.getIsCollection() ? (updateReqVO.getCollectionProxy() + " " + newCurrencyName) : "无");
            applyInfoList.add(infoVO);
            vo.setCollectionProxy(updateReqVO.getCollectionProxy());
            vo.setCollectionProxyCurrency(updateReqVO.getCollectionProxyCurrency());
        }
        // 单证报关
        if (!Objects.equals(vo.getCustomsType(), updateReqVO.getCustomsType())) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("单证报关/Document customs declaration");
            infoVO.setOrgValue(vo.getCustomsType() == 1 ? "我司全代/Our full representative" : (vo.getCustomsType() == 2 ? "自单代报/Self reporting" : "混合报关/Mixed customs declaration"));
            infoVO.setNewValue(updateReqVO.getCustomsType() == 1 ? "我司全代/Our full representative" : (updateReqVO.getCustomsType() == 2 ? "自单代报/Self reporting" : "混合报关/Mixed customs declaration"));
            vo.setCustomsType(updateReqVO.getCustomsType());
            vo.setIsCheckCoupon(Boolean.TRUE);
            applyInfoList.add(infoVO);
        }
        // 出单方式
        if ((Objects.isNull(vo.getIssuingMethod()) && Objects.nonNull(updateReqVO.getIssuingMethod()))
                || (Objects.nonNull(vo.getIssuingMethod()) && Objects.isNull(updateReqVO.getIssuingMethod()))
                || !Objects.equals(vo.getIssuingMethod(), updateReqVO.getIssuingMethod())) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("出单方式/Order issuing method");
            infoVO.setOrgValue(Objects.isNull(vo.getIssuingMethod()) ? "无" : (vo.getIssuingMethod() == 1 ? "电放/Telex Release" : "正本/original"));
            infoVO.setNewValue(Objects.isNull(updateReqVO.getIssuingMethod()) ? "无" : (updateReqVO.getIssuingMethod() == 1 ? "电放/Telex Release" : "正本/original"));
            vo.setIssuingMethod(updateReqVO.getIssuingMethod());
            applyInfoList.add(infoVO);
        }
        // 入仓类型
        if (!Objects.equals(vo.getWarehouseType(), updateReqVO.getWarehouseType())) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("入仓类型/Entry type");
            infoVO.setOrgValue(vo.getWarehouseType() == 1 ? "一次入仓/One time warehousing" : "分批入仓/Batch warehousing");
            infoVO.setNewValue(updateReqVO.getWarehouseType() == 1 ? "一次入仓/One time warehousing" : "分批入仓/Batch warehousing");
            vo.setWarehouseType(updateReqVO.getWarehouseType());
            applyInfoList.add(infoVO);
        }

        // 外部仓库
        if (Objects.equals(vo.getIsExternalWarehouse(), !updateReqVO.getIsExternalWarehouse()) ||
                (StringUtils.isBlank(vo.getExternalWarehouseJson()) && StringUtils.isNotBlank(updateReqVO.getExternalWarehouseJson())) ||
                !StringUtils.equals(vo.getExternalWarehouseJson(), updateReqVO.getExternalWarehouseJson())) {
            // 判断是否外部仓有变动
            if (Objects.equals(vo.getIsExternalWarehouse(), !updateReqVO.getIsExternalWarehouse())) {
                vo.setIsResetOrderNo(Boolean.TRUE);
            }
            infoVO = new ApplyInfoVO();
            infoVO.setName("外部仓库/External warehouse");
            infoVO.setOrgValue(vo.getIsExternalWarehouse() ? "是/yes" : "不是/no");
            infoVO.setNewValue(updateReqVO.getIsExternalWarehouse() ? "是/yes" : "不是/no");
            applyInfoList.add(infoVO);
            infoVO = new ApplyInfoVO();
            infoVO.setName("外部仓库地址变更/External warehouse address change");
            infoVO.setType(1);
            infoVO.setOrgExternalWarehouse(vo.getIsExternalWarehouse() ? vo.getExternalWarehouseDtoList() : null);
            infoVO.setNewExternalWarehouse(updateReqVO.getIsExternalWarehouse() ? updateReqVO.getExternalWarehouseDtoList() : null);
            applyInfoList.add(infoVO);
            vo.setIsExternalWarehouse(updateReqVO.getIsExternalWarehouse());
            if (updateReqVO.getIsExternalWarehouse()) {
                // 外部仓库信息
                if (CollectionUtil.isNotEmpty(updateReqVO.getExternalWarehouseDtoList())) {
                    vo.setExternalWarehouseJson(JSONObject.toJSONString(updateReqVO.getExternalWarehouseDtoList()));
                } else {
                    throw exception(ORDER_EXTERNAL_WAREHOUSE_NOT_NULL);
                }
            }
        }
        // 预计送货日期
        if (vo.getDeliveryDate().compareTo(updateReqVO.getDeliveryDate()) != 0) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("预计送货日期/Expected delivery date");
            infoVO.setOrgValue(DateUtil.format(vo.getDeliveryDate(), "yyyy-MM-dd"));
            infoVO.setNewValue(DateUtil.format(updateReqVO.getDeliveryDate(), "yyyy-MM-dd"));
            vo.setDeliveryDate(updateReqVO.getDeliveryDate());
            applyInfoList.add(infoVO);
        }
        // 收货方式
        if (!Objects.equals(vo.getHarvestMethod(), updateReqVO.getHarvestMethod())) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("收货方式/Receiving method");
            infoVO.setOrgValue(vo.getHarvestMethod() == 1 ? "自提/Self pickup" : "送货上门/provide home delivery service");
            infoVO.setNewValue(updateReqVO.getHarvestMethod() == 1 ? "自提/Self pickup" : "送货上门/provide home delivery service");
            vo.setHarvestMethod(updateReqVO.getHarvestMethod());
            if (updateReqVO.getHarvestMethod() == 2) {
                OrderConsigneeBackVO orderConsigneeBackVO = vo.getConsigneeVO();
                // 送货地址
                if(Objects.nonNull(orderConsigneeBackVO)) {
                    orderConsigneeBackVO.setCountry(updateReqVO.getCountry());
                    orderConsigneeBackVO.setProvince(updateReqVO.getProvince());
                    orderConsigneeBackVO.setCity(updateReqVO.getCity());
                    orderConsigneeBackVO.setAddress(updateReqVO.getConsigneeAddress());
                    orderConsigneeBackVO.setHarvestMethod(updateReqVO.getHarvestMethod());
                }
                vo.setConsigneeVO(orderConsigneeBackVO);
                vo.setCountry(updateReqVO.getCountry());
                vo.setProvince(updateReqVO.getProvince());
                vo.setCity(updateReqVO.getCity());
                vo.setConsigneeAddress(updateReqVO.getConsigneeAddress());
            } else {
                vo.setCountry(0L);
                vo.setProvince(0L);
                vo.setCity(0L);
                vo.setConsigneeAddress("");
            }
            applyInfoList.add(infoVO);
        }
        // 付款人
        if (!Objects.equals(vo.getDrawee(), updateReqVO.getDrawee())) {
            infoVO = new ApplyInfoVO();
            infoVO.setName("付款人/payer");
            infoVO.setOrgValue(DraweeEnum.valueOf(vo.getDrawee()).getName());
            infoVO.setNewValue(DraweeEnum.valueOf(updateReqVO.getDrawee()).getName());
            vo.setDrawee(updateReqVO.getDrawee());
            if (updateReqVO.getDrawee() == 3) {
                // 自定义付款人
                if (CollectionUtil.isNotEmpty(updateReqVO.getCustomDraweeVOList())) {
                    vo.setCustomDrawee(JSONObject.toJSONString(updateReqVO.getCustomDraweeVOList()));
                } else {
                    throw exception(ORDER_CUSTOM_DRAWEE_INFO_NOT_NULL);
                }
            }
            applyInfoList.add(infoVO);
            vo.setIsCharge(true);
            vo.setIsDrawee(true);
        }

        // 付款人
        if (vo.getDrawee() == 3 && Objects.equals(vo.getDrawee(), updateReqVO.getDrawee())) {
            // 自定义付款人需要比较自定义付款详情列表
            if (CollectionUtil.isEmpty(updateReqVO.getCustomDraweeVOList())) {
                throw exception(ORDER_CUSTOM_DRAWEE_INFO_NOT_NULL);
            }
            Map<String, CustomDraweeVO> voCustomDraweeMap = vo.getCustomDraweeVOList().stream().collect(Collectors.groupingBy(CustomDraweeVO::getName, Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0))));
            List<CustomDraweeVO> customDraweeVOList = updateReqVO.getCustomDraweeVOList().stream()
                    .filter(updateCustomDrawee -> Objects.nonNull(voCustomDraweeMap.get(updateCustomDrawee.getName())) &&
                            !Objects.equals(voCustomDraweeMap.get(updateCustomDrawee.getName()).getValue(), updateCustomDrawee.getValue())).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(customDraweeVOList)) {
                for (CustomDraweeVO customDraweeVO : customDraweeVOList) {
                    infoVO = new ApplyInfoVO();
                    CustomDraweeEnum customDraweeEnum = CustomDraweeEnum.keyOf(customDraweeVO.getName());
                    infoVO.setName(String.format("自定义%s付款人", customDraweeEnum.getName()) + String.format("Custom %s payer", customDraweeEnum.getNameEn()));
                    DraweeEnum orgDraweeEnum = DraweeEnum.valueOf(customDraweeVO.getValue() == 1 ? 2 : 1);
                    DraweeEnum newDraweeEnum = DraweeEnum.valueOf(customDraweeVO.getValue());
                    infoVO.setOrgValue(orgDraweeEnum.getName() + "/" + orgDraweeEnum.getNameEn());
                    infoVO.setNewValue(newDraweeEnum.getName() + "/" + newDraweeEnum.getNameEn());
                    applyInfoList.add(infoVO);
                }
//                vo.setDrawee(updateReqVO.getDrawee());
                vo.setCustomDrawee(JSONObject.toJSONString(updateReqVO.getCustomDraweeVOList()));
                vo.setIsCharge(true);
                vo.setIsDrawee(true);
            }

        }

    }


    /**
     * @param orderId        订单ID
     * @param packageType    特需类型字符串
     * @param packageRemarks 特需备注
     * @param userId         更新用户
     * @param now            时间
     */
    private void saveOrUpdateSpecialNeed(Long orderId, String packageType, String packageRemarks, String
            userId, Date now) {
        List<OrderSpecialNeedDO> needDOList = orderSpecialNeedService.getListByOrderId(orderId);
        if (CollectionUtil.isNotEmpty(needDOList)) {
            List<String> packageTypes = StringUtils.isNotBlank(packageType) ? Arrays.asList(packageType.split(StrUtil.COMMA)) : new ArrayList<>();
            List<OrderSpecialNeedDO> deleteNeedDOList;
            if (CollectionUtil.isNotEmpty(packageTypes)) {
                deleteNeedDOList = needDOList.stream().filter(need -> !packageTypes.contains(need.getAdvanceType())).collect(Collectors.toList());
            } else {
                deleteNeedDOList = new ArrayList<>(needDOList);
            }
            // 删除特需
            if (CollectionUtil.isNotEmpty(deleteNeedDOList)) {
                for (OrderSpecialNeedDO orderSpecialNeedDO : deleteNeedDOList) {
                    orderSpecialNeedService.deleteOrderSpecialNeed(orderSpecialNeedDO.getId());
                }

                needDOList.removeAll(deleteNeedDOList);
            }
            for (String type : packageTypes) {
                boolean flag = true;
                for (OrderSpecialNeedDO orderSpecialNeedDO : needDOList) {
                    if (Objects.equals(type, orderSpecialNeedDO.getAdvanceType())) {
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    OrderSpecialNeedDO orderSpecialNeedDO = new OrderSpecialNeedDO();
                    orderSpecialNeedDO.setOrderId(orderId);
                    orderSpecialNeedDO.setAdvanceType(type);
                    orderSpecialNeedDO.setCreateTime(now);
                    orderSpecialNeedDO.setUpdateTime(now);
                    orderSpecialNeedDO.setTransFee(BigDecimal.ZERO);
                    orderSpecialNeedDO.setTransCurrency(1);
                    orderSpecialNeedDO.setTodoDetail(packageRemarks);
                    orderSpecialNeedDO.setCreator(userId);
                    orderSpecialNeedDO.setUpdater(userId);
                    orderSpecialNeedService.save(orderSpecialNeedDO);
                }
            }
        } else {
            if (StringUtils.isNotBlank(packageType)) {
                String[] packageTypes = packageType.split(StrUtil.COMMA);
                List<OrderSpecialNeedCreateReqVO> createReqVOList = new ArrayList<>();
                for (String type : packageTypes) {
                    OrderSpecialNeedCreateReqVO reqVO = new OrderSpecialNeedCreateReqVO();
                    reqVO.setOrderId(orderId);
                    reqVO.setAdvanceType(type);
                    reqVO.setTodoDetail(packageRemarks);
                    reqVO.setTransFee(BigDecimal.ZERO);
                    reqVO.setTransCurrency(1);
                    createReqVOList.add(reqVO);
                }
                // TODO 订单更新时新增的特需都不需要校验异常审批类型
                orderSpecialNeedService.createOrderSpecialNeed(createReqVOList, Boolean.FALSE);
            }
        }
    }

    private void appUpdateConsignorAndConsignee(OrderUpdateReqVO updateReqVO,
                                                OrderDO updateObj,
                                                String updater,
                                                Date now,
                                                MemberUserDO memberUserDO,
                                                DictDataRespDTO dictDataRespDTO) {
        // 根据会员ID获取客户联系人ID与客户ID
        CustomerContactsDO customerContacts = customerContactsService.getOne(new LambdaQueryWrapper<CustomerContactsDO>()
                .and(we -> we.eq(CustomerContactsDO::getUserid, memberUserDO.getId())
                        .or()
                        .eq(CustomerContactsDO::getPhoneNew, memberUserDO.getMobile())
                        .eq(CustomerContactsDO::getAreaCode, memberUserDO.getAreaCode())).eq(CustomerContactsDO::getDeleted, 0).last("limit 1"));
        OrderConsignorDO orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, updateObj.getOrderId()).orderByDesc(OrderConsignorDO::getId).last("limit 1"));
        if (Objects.isNull(orderConsignorDO)) {
            orderConsignorDO = new OrderConsignorDO();
        }
        orderConsignorDO.setOrderId(updateObj.getOrderId());
        orderConsignorDO.setCreator(updater);
        orderConsignorDO.setUpdater(updater);
        if (Objects.isNull(customerContacts)) {
            // 如果客户联系人为空，则创建新的客户信息，重新查询
            customerApi.associateCustomerAuto(memberUserDO.getAreaCode(), memberUserDO.getMobile(), memberUserDO.getId(), memberUserDO.getNickname(), memberUserDO.getCode());
            customerContacts = customerContactsService.getOne(new LambdaQueryWrapper<CustomerContactsDO>()
                    .and(we -> we.eq(CustomerContactsDO::getUserid, memberUserDO.getId())
                            .or()
                            .eq(CustomerContactsDO::getPhoneNew, memberUserDO.getMobile())
                            .eq(CustomerContactsDO::getAreaCode, memberUserDO.getAreaCode())).eq(CustomerContactsDO::getDeleted, 0).last("limit 1"));
        }
        CustomerDO consignorCustomerDO = null;
        boolean hasConsignee = Objects.nonNull(updateReqVO.getHasConsignee()) ? updateReqVO.getHasConsignee() : true;
        if (Objects.nonNull(customerContacts)) {
            consignorCustomerDO = customerService.getCustomer(customerContacts.getCustomerId());
            if (consignorCustomerDO != null) {
                orderConsignorDO.setCompany(consignorCustomerDO.getCompany());
                orderConsignorDO.setCompanyEn(consignorCustomerDO.getCompanyEn());
                orderConsignorDO.setCustomerNumber(consignorCustomerDO.getNumber());
                CountryDO consignorCountryDO = countryService.getById(consignorCustomerDO.getCountry());
                if (consignorCountryDO != null) {
                    orderConsignorDO.setCountryAbbreviation(consignorCountryDO.getNameShort());
                }
            }
            if (StringUtils.isBlank(customerContacts.getPhoneNew())) {
                throw exception(CONSIGNOR_PHONE_NOT_NULL);
            }
            if (StringUtils.isBlank(customerContacts.getAreaCode())) {
                throw exception(CONSIGNOR_PHONE_CODE_NOT_NULL);
            }
            orderConsignorDO.setCustomerContactsId(customerContacts.getId());
            orderConsignorDO.setCustomerId(customerContacts.getCustomerId());
            orderConsignorDO.setEmail(customerContacts.getEmail());
        }
        if (StringUtils.isBlank(memberUserDO.getMobile())) {
            throw exception(CONSIGNOR_PHONE_NOT_NULL);
        }
        if (StringUtils.isBlank(memberUserDO.getAreaCode())) {
            throw exception(CONSIGNOR_PHONE_CODE_NOT_NULL);
        }
        orderConsignorDO.setName(memberUserDO.getNickname());
        orderConsignorDO.setNameEn(memberUserDO.getEnglishName());
        orderConsignorDO.setCountryCode(memberUserDO.getAreaCode());
        orderConsignorDO.setPhone(memberUserDO.getMobile());
        if (StringUtils.isNotBlank(memberUserDO.getEmail())) {
            orderConsignorDO.setEmail(memberUserDO.getEmail());
        }
        if (StringUtils.isNotBlank(memberUserDO.getEnterpriseName())) {
            orderConsignorDO.setCompany(memberUserDO.getEnterpriseName());
        }
        if (StringUtils.isNotBlank(memberUserDO.getEnterpriseNameEn())) {
            orderConsignorDO.setCompanyEn(memberUserDO.getEnterpriseNameEn());
        }
        orderConsignorDO.setRelationId(updateReqVO.getUserId());
        orderConsignorDO.setCreateTime(now);
        orderConsignorDO.setUpdateTime(now);
        if (StringUtils.isBlank(orderConsignorDO.getPhone()) || StringUtils.isBlank(orderConsignorDO.getCountryCode())) {
            throw exception(ORDER_CONSIGNOR_PHONE_INFO_NOT_COMPLETE);
        }
        if (StringUtils.isBlank(orderConsignorDO.getName())) {
            throw exception(ORDER_CONSIGNOR_NAME_NOT_COMPLETE);
        }
        try {
            String mobileCode = orderConsignorDO.getCountryCode() + StrUtil.COLON + orderConsignorDO.getPhone();
            paramValidatorService.validatorMobile(mobileCode);
        } catch (Exception e) {
            throw exception(ORDER_CONSIGNOR_PHONE_INCORRECT_FORMAT);
        }
        orderConsignorService.saveOrUpdate(orderConsignorDO);
        if (updateObj.getIsCargoControl()) {
            OrderCargoControlDO orgOrderCargoControlDO = orderCargoControlMapper.selectOne(new LambdaQueryWrapper<OrderCargoControlDO>().eq(OrderCargoControlDO::getOrderId, updateObj.getOrderId()).eq(OrderCargoControlDO::getIsActual, Boolean.TRUE).last("limit 1"));
            // 控货订单 添加控货人信息
            OrderCargoControlDO orderCargoControlDO = new OrderCargoControlDO();
            orderConsignorDO.setId(null);
            BeanUtils.copyProperties(orderConsignorDO, orderCargoControlDO);
            orderCargoControlDO.setDialCode(Integer.valueOf(orderConsignorDO.getCountryCode()));
            orderCargoControlDO.setIso2(orderConsignorDO.getCountryAbbreviation());
            orderCargoControlDO.setOrderNo(updateObj.getOrderNo());
            orderCargoControlDO.setTidanNo(updateObj.getTidanNo());
            orderCargoControlDO.setCreator(updater);
            orderCargoControlDO.setCreateTime(now);
            orderCargoControlDO.setIsActual(Boolean.TRUE);
            if (Objects.isNull(orgOrderCargoControlDO)) {
                orderCargoControlMapper.insert(orderCargoControlDO);
                // TODO 订单控货信息日志补充
                String msg = String.format("订单创建默认发货人控货信息，姓名%s，电话+%s", orderConsignorDO.getName() + "/" + (StringUtils.isNotBlank(orderConsignorDO.getNameEn()) ? orderConsignorDO.getNameEn() : "空"),
                        orderConsignorDO.getCountryCode() + orderConsignorDO.getPhone());
                orderBusinessService.createOrderControlLog(orderCargoControlDO.getOrderId(), 1, "创建控货信息", msg, 0L);
            } else {
                orderCargoControlDO.setId(orgOrderCargoControlDO.getId());
                orderCargoControlMapper.updateById(orderCargoControlDO);
                // TODO 订单控货信息日志补充
                String msg = String.format("订单跟新默认发货人控货信息，姓名%s，电话+%s", orderConsignorDO.getName() + "/" + (StringUtils.isNotBlank(orderConsignorDO.getNameEn()) ? orderConsignorDO.getNameEn() : "空"),
                        orderConsignorDO.getCountryCode() + orderConsignorDO.getPhone());
                orderBusinessService.createOrderControlLog(orderCargoControlDO.getOrderId(), 2, "更新控货信息", msg, 0L);
            }
        }

        OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, updateObj.getOrderId()).orderByDesc(OrderConsigneeDO::getId).last("limit 1"));
        if (!updateObj.getIsCargoControl() || hasConsignee) {
            // 控货订单有收货人则限制修改收货人
            if (updateObj.getIsCargoControl() && hasConsignee) {
                updateObj.setIsLimitUpdateConsignee(Boolean.TRUE);
            } else {
                updateObj.setIsLimitUpdateConsignee(Boolean.FALSE);
            }
            if (Objects.isNull(orderConsigneeDO)) {
                orderConsigneeDO = new OrderConsigneeDO();
            }
            orderConsigneeDO.setOrderId(updateObj.getOrderId());
            orderConsigneeDO.setCreator(updater);
            orderConsigneeDO.setUpdater(updater);

            if (StringUtils.isBlank(updateReqVO.getConsigneePhone())) {
                throw exception(CONSIGNEE_PHONE_NOT_NULL);
            }
            if (StringUtils.isBlank(updateReqVO.getCountryCode())) {
                throw exception(CONSIGNEE_PHONE_CODE_NOT_NULL);
            }
            orderConsigneeDO.setPhone(updateReqVO.getConsigneePhone());
            orderConsigneeDO.setName(StringUtils.isNotBlank(updateReqVO.getConsigneeName()) ? updateReqVO.getConsigneeName() : updateReqVO.getConsigneePhone());
            orderConsigneeDO.setNameEn(Objects.isNull(updateReqVO.getConsigneeNameEn()) ? "" : updateReqVO.getConsigneeNameEn());
            orderConsigneeDO.setCountryCode(updateReqVO.getCountryCode());
            orderConsigneeDO.setEmail(updateReqVO.getConsigneeEmail());
            orderConsigneeDO.setCompany(updateReqVO.getConsigneeCompany());
            orderConsigneeDO.setCompanyEn(updateReqVO.getConsigneeCompanyEn());

            orderConsigneeDO.setHarvestMethod(updateReqVO.getHarvestMethod()); // 收货方式
            if (Objects.nonNull(updateReqVO.getHarvestMethod()) && updateReqVO.getHarvestMethod() == 2) {
                if (StringUtils.isNotBlank(updateReqVO.getConsigneeAddress())) {
                    orderConsigneeDO.setAddress(updateReqVO.getConsigneeAddress());
                }
            } else {
                orderConsigneeDO.setAddress("");
            }
            orderConsigneeDO.setCountry(updateReqVO.getCountry());
            orderConsigneeDO.setProvince(updateReqVO.getProvince());
            orderConsigneeDO.setCity(updateReqVO.getCity());
            orderConsigneeDO.setRelationId(updateReqVO.getUserId());
            orderConsigneeDO.setCreateTime(now);
            orderConsigneeDO.setUpdateTime(now);
            if (StringUtils.isBlank(orderConsigneeDO.getPhone()) || StringUtils.isBlank(orderConsigneeDO.getCountryCode())) {
                throw exception(ORDER_CONSIGNEE_PHONE_INFO_NOT_COMPLETE);
            }
            if (StringUtils.isBlank(orderConsigneeDO.getName())) {
                throw exception(ORDER_CONSIGNEE_NAME_NOT_COMPLETE);
            }
            if (updateReqVO.getHasConsignee() && Objects.nonNull(updateReqVO.getIsCargoControl()) && updateReqVO.getIsCargoControl() && StringUtils.isNotBlank(orderConsigneeDO.getCountryCode()) &&
                    Objects.nonNull(dictDataRespDTO) && StringUtils.equals("11", dictDataRespDTO.getValue()) && StringUtils.equals("86", orderConsigneeDO.getCountryCode())) {
                throw exception(CONSIGNEE_PHONE_IS_EXTERNAL);
            }
            try {
                String mobileCode = orderConsigneeDO.getCountryCode() + StrUtil.COLON + orderConsigneeDO.getPhone();
                paramValidatorService.validatorMobile(mobileCode);
            } catch (Exception e) {
                throw exception(ORDER_CONSIGNEE_PHONE_INCORRECT_FORMAT);
            }
            //todo 需要判断手机号唯一性，判断规则：1.区号相同，2.先判断手机号码是否存在，然后再判断：a.如果是0开头，判断是否存在非0开头号码；b.如果非0开头，判断是否存在0开头号码
            CustomerContactsDO consignee = customerContactsService.getUniqueOneAndValidate(orderConsigneeDO.getCountryCode(), orderConsigneeDO.getPhone(), null);
            if (Objects.nonNull(consignee) && Objects.nonNull(consignee.getCustomerId())) {
                orderConsigneeDO.setCustomerId(consignee.getCustomerId());
                orderConsigneeDO.setCustomerContactsId(consignee.getId());
                CustomerDO consigneeDO = customerService.getCustomer(consignee.getCustomerId());
                if (Objects.nonNull(consigneeDO)) {
                    orderConsignorDO.setCustomerNumber(consigneeDO.getNumber());
                }
            } else {
                // 客户不存在，新增客户联系人信息 orderConsigneeDO中有值
                // 20230511 收货人无客户档案时 判断发货人有无客户经理，没有 生成客户档案，进入待分配。	有客户经理，则暂时不生成客户档案。(放在入仓时处理）
                if (consignorCustomerDO == null || consignorCustomerDO.getCustomerService() == null || consignorCustomerDO.getCustomerService() == 0) {
                    CustomerContactsDO consigeeCustomer = customerService.createConsigeeCustomer(orderConsigneeDO.getName(),
                            orderConsigneeDO.getCountryCode(), orderConsigneeDO.getPhone(), orderConsigneeDO.getCompany(), orderConsigneeDO.getEmail(), consignorCustomerDO, updateObj.getOrderNo());
                    if (consigeeCustomer != null) {
                        orderConsigneeDO.setCustomerId(consigeeCustomer.getCustomerId());
                        orderConsigneeDO.setCustomerContactsId(consigeeCustomer.getId());
                        CustomerDO consigneeDO = customerService.getCustomer(consigeeCustomer.getCustomerId());
                        if (Objects.nonNull(consigneeDO)) {
                            orderConsignorDO.setCustomerNumber(consigneeDO.getNumber());
                        }
                    }
                }
            }
            orderConsigneeService.saveOrUpdate(orderConsigneeDO);
        } else {
            // 如果控货订单发货人设置了控货无收货人，则需要删除订单已有收货人
            if (Objects.nonNull(orderConsigneeDO) && !hasConsignee) {
                orderConsigneeService.removeById(orderConsigneeDO.getId());
                orderConsigneeDO = null;
            }
            // 控货订单没有收货人则不限制修改收货人
            if (updateObj.getIsCargoControl() && hasConsignee) {
                updateObj.setIsLimitUpdateConsignee(Boolean.TRUE);
            } else {
                updateObj.setIsLimitUpdateConsignee(Boolean.FALSE);
            }
        }
        if (!Objects.equals(updateReqVO.getStatus(),
                DRAFT.getValue())) {

            //customerType 发货人 1 收货人 2
            int customerType =
                    this.checkOrderSalesman(updateObj,
                            updateReqVO.getOfferId(),
                            consignorCustomerDO,
                            null,
                            orderConsignorDO,
                            orderConsigneeDO);
            // 更新所属客户经理(业务员)
            if (!DRAFT.getValue().equals(updateObj.getStatus())
                    && ((Objects.nonNull(updateObj.getIsChargeCustomer()) && updateObj.getIsChargeCustomer())
                    || (Objects.nonNull(updateObj.getIsChargeDraft()) && updateObj.getIsChargeDraft()))) {
                addOrderCustomerService(updateObj, customerType);
            }
        }
    }

    private void adminUpdateConsignorAndConsignee(OrderUpdateReqVO updateReqVO,
                                                  OrderDO updateObj,
                                                  String updater,
                                                  Date now,
                                                  DictDataRespDTO dictDataRespDTO) {

        CustomerDO consignorDO = customerService.getCustomer(updateReqVO.getConsignorId());
        CustomerContactsDO consignorContactsDO = customerContactsService.getCustomerContacts(updateReqVO.getConsignorContactsId());

        OrderConsignorDO orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, updateObj.getOrderId()).orderByDesc(OrderConsignorDO::getId).last("limit 1"));
        if (Objects.isNull(orderConsignorDO)) {
            orderConsignorDO = new OrderConsignorDO();
        }
        boolean hasConsignee = Objects.nonNull(updateReqVO.getHasConsignee()) ? updateReqVO.getHasConsignee() : true;
        if (Objects.nonNull(consignorDO)) {
            orderConsignorDO.setCompany(consignorDO.getCompany());
            orderConsignorDO.setCompanyEn(consignorDO.getCompanyEn());
            orderConsignorDO.setCustomerNumber(consignorDO.getNumber());
            CountryDO consignorCountryDO = countryService.getById(consignorDO.getCountry());
            orderConsignorDO.setCountryAbbreviation(Objects.isNull(consignorCountryDO) ? null : consignorCountryDO.getNameShort());
        }

        if (Objects.nonNull(consignorContactsDO)) {
            if (StringUtils.isBlank(consignorContactsDO.getPhoneNew())) {
                throw exception(CONSIGNOR_PHONE_NOT_NULL);
            }
            if (StringUtils.isBlank(consignorContactsDO.getAreaCode())) {
                throw exception(CONSIGNOR_PHONE_CODE_NOT_NULL);
            }
            orderConsignorDO.setName(consignorContactsDO.getName());
            orderConsignorDO.setNameEn(consignorContactsDO.getNameEn());
            orderConsignorDO.setCountryCode(consignorContactsDO.getAreaCode());
            orderConsignorDO.setEmail(consignorContactsDO.getEmail());
            orderConsignorDO.setPhone(consignorContactsDO.getPhoneNew());
            orderConsignorDO.setCustomerContactsId(consignorContactsDO.getId());
            orderConsignorDO.setCustomerId(consignorContactsDO.getCustomerId());
        } else {
            if (!Objects.equals(updateReqVO.getStatus(), DRAFT.getValue())) {
                if (StringUtils.isBlank(updateReqVO.getConsignorPhone())) {
                    throw exception(CONSIGNOR_PHONE_NOT_NULL);
                }
                if (StringUtils.isBlank(updateReqVO.getConsignorCountryCode())) {
                    throw exception(CONSIGNOR_PHONE_CODE_NOT_NULL);
                }
            }
            orderConsignorDO.setCustomerContactsId(updateReqVO.getConsignorContactsId());
            orderConsignorDO.setCustomerId(updateReqVO.getConsignorId());
            orderConsignorDO.setName(updateReqVO.getConsignorName());
            orderConsignorDO.setCountryCode(updateReqVO.getConsignorCountryCode());
            orderConsignorDO.setEmail(updateReqVO.getConsignorEmail());
            orderConsignorDO.setPhone(updateReqVO.getConsignorPhone());
        }
        orderConsignorDO.setOrderId(updateObj.getOrderId());
        orderConsignorDO.setUpdater(updater);

        orderConsignorDO.setRelationId(updateObj.getCustomerId());

        orderConsignorDO.setUpdateTime(now);
        if (!Objects.equals(updateReqVO.getStatus(), DRAFT.getValue())) {
            if (StringUtils.isBlank(orderConsignorDO.getPhone()) || StringUtils.isBlank(orderConsignorDO.getCountryCode())) {
                throw exception(ORDER_CONSIGNOR_PHONE_INFO_NOT_COMPLETE);
            }
            if (StringUtils.isBlank(orderConsignorDO.getName())) {
                throw exception(ORDER_CONSIGNOR_NAME_NOT_COMPLETE);
            }
            if (StringUtils.isNotBlank(orderConsignorDO.getPhone()) && StringUtils.isNotBlank(orderConsignorDO.getCountryCode())) {
                try {
                    String mobileCode = orderConsignorDO.getCountryCode() + StrUtil.COLON + orderConsignorDO.getPhone();
                    paramValidatorService.validatorMobile(mobileCode);
                } catch (Exception e) {
                    throw exception(ORDER_CONSIGNOR_PHONE_INCORRECT_FORMAT);
                }
            }
        }
        if (StringUtils.isNotBlank(updateReqVO.getConsignorName())) {
            orderConsignorDO.setName(updateReqVO.getConsignorName());
        }
        if (StringUtils.isNotBlank(updateReqVO.getConsignorNameEn())) {
            orderConsignorDO.setNameEn(updateReqVO.getConsignorNameEn());
        }
        if (StringUtils.isNotBlank(updateReqVO.getConsignorCompany())) {
            orderConsignorDO.setCompany(updateReqVO.getConsignorCompany());
        }
        if (StringUtils.isNotBlank(updateReqVO.getConsignorCompanyEn())) {
            orderConsignorDO.setCompanyEn(updateReqVO.getConsignorCompanyEn());
        }
        if (StringUtils.isNotBlank(updateReqVO.getConsignorEmail())) {
            orderConsignorDO.setEmail(updateReqVO.getConsignorEmail());
        }
        if (StringUtils.isNotBlank(orderConsignorDO.getPhone())) {
            orderConsignorService.saveOrUpdate(orderConsignorDO);
        }
        if (updateObj.getIsCargoControl() && !Objects.equals(updateReqVO.getStatus(), DRAFT.getValue())) {
            OrderCargoControlDO orgOrderCargoControlDO = orderCargoControlMapper.selectOne(new LambdaQueryWrapper<OrderCargoControlDO>().eq(OrderCargoControlDO::getOrderId, updateObj.getOrderId()).eq(OrderCargoControlDO::getIsActual, Boolean.TRUE).last("limit 1"));
            // 控货订单 添加控货人信息
            OrderCargoControlDO orderCargoControlDO = new OrderCargoControlDO();
            orderConsignorDO.setId(null);
            BeanUtils.copyProperties(orderConsignorDO, orderCargoControlDO);
            orderCargoControlDO.setDialCode(Integer.valueOf(orderConsignorDO.getCountryCode()));
            orderCargoControlDO.setIso2(orderConsignorDO.getCountryAbbreviation());
            orderCargoControlDO.setOrderNo(updateObj.getOrderNo());
            orderCargoControlDO.setTidanNo(updateObj.getTidanNo());
            orderCargoControlDO.setCreator(updater);
            orderCargoControlDO.setCreateTime(now);
            orderCargoControlDO.setIsActual(Boolean.TRUE);
            if (Objects.isNull(orgOrderCargoControlDO)) {
                orderCargoControlMapper.insert(orderCargoControlDO);
                // TODO 订单控货信息日志补充
                String msg = String.format("订单创建默认发货人控货信息，姓名%s，电话+%s", orderConsignorDO.getName() + "/" + (StringUtils.isNotBlank(orderConsignorDO.getNameEn()) ? orderConsignorDO.getNameEn() : "空"),
                        orderConsignorDO.getCountryCode() + orderConsignorDO.getPhone());
                orderBusinessService.createOrderControlLog(orderCargoControlDO.getOrderId(), 1, "创建控货信息", msg, 0L);
            } else {
                orderCargoControlDO.setId(orgOrderCargoControlDO.getId());
                orderCargoControlMapper.updateById(orderCargoControlDO);
                // TODO 订单控货信息日志补充
                String msg = String.format("订单更新默认发货人控货信息，姓名%s，电话+%s", orderConsignorDO.getName() + "/" + (StringUtils.isNotBlank(orderConsignorDO.getNameEn()) ? orderConsignorDO.getNameEn() : "空"),
                        orderConsignorDO.getCountryCode() + orderConsignorDO.getPhone());
                orderBusinessService.createOrderControlLog(orderCargoControlDO.getOrderId(), 2, "更新控货信息", msg, 0L);
            }
        }

        CustomerDO consigneeDO = customerService.getCustomer(updateReqVO.getConsigneeId());

        OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, updateObj.getOrderId()).orderByDesc(OrderConsigneeDO::getId).last("limit 1"));

        if (!updateObj.getIsCargoControl() || hasConsignee) {
            // 控货订单有收货人则限制修改收货人
            if (updateObj.getIsCargoControl() && hasConsignee) {
                updateObj.setIsLimitUpdateConsignee(Boolean.TRUE);
            } else {
                updateObj.setIsLimitUpdateConsignee(Boolean.FALSE);
            }
            if (Objects.isNull(orderConsigneeDO)) {
                orderConsigneeDO = new OrderConsigneeDO();
            }
            if (consigneeDO != null) {
                orderConsigneeDO.setCompany(consigneeDO.getCompany());
                orderConsigneeDO.setCompanyEn(consigneeDO.getCompanyEn());
                orderConsigneeDO.setAddress(consigneeDO.getAddress());
                orderConsigneeDO.setCustomerNumber(consigneeDO.getNumber());
                CountryDO consigneeCountryDO = countryService.getById(consigneeDO.getCountry());
                if (consigneeCountryDO != null) {
                    orderConsignorDO.setCountryAbbreviation(consigneeCountryDO.getNameShort());
                }
            } else {
                orderConsigneeDO.setCompany(updateReqVO.getConsigneeCompany());
                orderConsigneeDO.setCompanyEn(updateReqVO.getConsigneeCompanyEn());
                orderConsigneeDO.setAddress(updateReqVO.getConsigneeAddress());
                orderConsignorDO.setCountryAbbreviation(updateReqVO.getCountryAbbreviation());
            }
            CustomerContactsDO consigneeContactsDO = customerContactsService.getCustomerContacts(updateReqVO.getConsigneeContactsId());
            if (null != consigneeContactsDO) {
                if (StringUtils.isBlank(consigneeContactsDO.getPhoneNew())) {
                    throw exception(CONSIGNEE_PHONE_NOT_NULL);
                }
                if (StringUtils.isBlank(consigneeContactsDO.getAreaCode())) {
                    throw exception(CONSIGNEE_PHONE_CODE_NOT_NULL);
                }
                orderConsigneeDO.setName(consigneeContactsDO.getName());
                orderConsigneeDO.setNameEn(consigneeContactsDO.getNameEn());
                orderConsigneeDO.setCountryCode(consigneeContactsDO.getAreaCode());
                orderConsigneeDO.setEmail(consigneeContactsDO.getEmail());
                orderConsigneeDO.setPhone(consigneeContactsDO.getPhoneNew());
                orderConsigneeDO.setCustomerContactsId(consigneeContactsDO.getId());
                orderConsigneeDO.setCustomerId(consigneeContactsDO.getCustomerId());
            } else {
                if (!Objects.equals(updateReqVO.getStatus(), DRAFT.getValue())) {
                    if (StringUtils.isBlank(updateReqVO.getConsigneePhone())) {
                        throw exception(CONSIGNEE_PHONE_NOT_NULL);
                    }
                    if (StringUtils.isBlank(updateReqVO.getCountryCode()) && StringUtils.isBlank(updateReqVO.getConsigneeCountryCode())) {
                        throw exception(CONSIGNEE_PHONE_CODE_NOT_NULL);
                    }
                }
                orderConsigneeDO.setCustomerContactsId(updateReqVO.getConsigneeContactsId());
                orderConsigneeDO.setCustomerId(updateReqVO.getConsigneeId());
                orderConsigneeDO.setName(updateReqVO.getConsigneeName());
                orderConsigneeDO.setNameEn(updateReqVO.getConsigneeNameEn());
                orderConsigneeDO.setCountryCode(Objects.nonNull(updateReqVO.getCountryCode()) ? updateReqVO.getCountryCode() : updateReqVO.getConsigneeCountryCode());
                orderConsigneeDO.setEmail(updateReqVO.getConsigneeEmail());
                orderConsigneeDO.setPhone(updateReqVO.getConsigneePhone());
            }
            if (updateReqVO.getHasConsignee() && Objects.nonNull(updateReqVO.getIsCargoControl()) && updateReqVO.getIsCargoControl() && StringUtils.isNotBlank(orderConsigneeDO.getCountryCode()) &&
                    Objects.nonNull(dictDataRespDTO) && StringUtils.equals("11", dictDataRespDTO.getValue()) && StringUtils.equals("86", orderConsigneeDO.getCountryCode())) {
                throw exception(CONSIGNEE_PHONE_IS_EXTERNAL);
            }
            orderConsigneeDO.setHarvestMethod(updateReqVO.getHarvestMethod()); // 收货方式
            if (Objects.nonNull(updateReqVO.getHarvestMethod()) && updateReqVO.getHarvestMethod() == 2) {
                if (StringUtils.isNotBlank(updateReqVO.getConsigneeAddress())) {
                    orderConsigneeDO.setAddress(updateReqVO.getConsigneeAddress());
                }
            } else {
                orderConsigneeDO.setAddress("");
            }
            orderConsigneeDO.setOrderId(updateObj.getOrderId());
            orderConsigneeDO.setUpdater(updater);
            orderConsigneeDO.setCountry(updateReqVO.getCountry());
            orderConsigneeDO.setProvince(updateReqVO.getProvince());
            orderConsigneeDO.setCity(updateReqVO.getCity());
            orderConsigneeDO.setRelationId(updateReqVO.getCustomerId());

            orderConsigneeDO.setUpdateTime(now);
            if (!Objects.equals(updateReqVO.getStatus(), DRAFT.getValue())) {
                if (StringUtils.isBlank(orderConsigneeDO.getPhone()) || StringUtils.isBlank(orderConsigneeDO.getCountryCode())) {
                    throw exception(ORDER_CONSIGNEE_PHONE_INFO_NOT_COMPLETE);
                }
                if (StringUtils.isBlank(orderConsigneeDO.getName())) {
                    throw exception(ORDER_CONSIGNEE_NAME_NOT_COMPLETE);
                }
                try {
                    String mobileCode = orderConsigneeDO.getCountryCode() + StrUtil.COLON + orderConsigneeDO.getPhone();
                    paramValidatorService.validatorMobile(mobileCode);
                } catch (Exception e) {
                    throw exception(ORDER_CONSIGNEE_PHONE_INCORRECT_FORMAT);
                }
            }
            if (StringUtils.isNotBlank(updateReqVO.getConsigneeName())) {
                orderConsigneeDO.setName(updateReqVO.getConsigneeName());
            }
            if (StringUtils.isNotBlank(updateReqVO.getConsigneeNameEn())) {
                orderConsigneeDO.setNameEn(updateReqVO.getConsigneeNameEn());
            }
            if (StringUtils.isNotBlank(updateReqVO.getConsigneeCompany())) {
                orderConsigneeDO.setCompany(updateReqVO.getConsigneeCompany());
            }
            if (StringUtils.isNotBlank(updateReqVO.getConsigneeCompanyEn())) {
                orderConsigneeDO.setCompanyEn(updateReqVO.getConsigneeCompanyEn());
            }
            if (StringUtils.isNotBlank(updateReqVO.getConsigneeEmail())) {
                orderConsigneeDO.setEmail(updateReqVO.getConsigneeEmail());
            }
            if (StringUtils.isNotBlank(orderConsigneeDO.getPhone())) {
                orderConsigneeService.saveOrUpdate(orderConsigneeDO);
            }
        } else {
            // 如果控货订单发货人设置了控货无收货人，则需要删除订单已有收货人
            if (Objects.nonNull(orderConsigneeDO) && !hasConsignee) {
                orderConsigneeService.removeById(orderConsigneeDO.getId());
                orderConsigneeDO = null;
            }
            consigneeDO = null;
            // 控货订单没有收货人则不限制修改收货人
            if (updateObj.getIsCargoControl() && hasConsignee) {
                updateObj.setIsLimitUpdateConsignee(Boolean.TRUE);
            } else {
                updateObj.setIsLimitUpdateConsignee(Boolean.FALSE);
            }
        }
        if (!Objects.equals(updateReqVO.getStatus(),
                DRAFT.getValue())) {
            //customerType 发货人 1 收货人 2
            int customerType = this.checkOrderSalesman(updateObj,
                    updateReqVO.getOfferId(),
                    consignorDO,
                    consigneeDO,
                    orderConsignorDO,
                    orderConsigneeDO);

            // 更新所属客户经理(业务员)
            if (!DRAFT.getValue().equals(updateObj.getStatus())
                    && ((Objects.nonNull(updateObj.getIsChargeCustomer()) && updateObj.getIsChargeCustomer())
                    || (Objects.nonNull(updateObj.getIsChargeDraft()) && updateObj.getIsChargeDraft()))) {
                addOrderCustomerService(updateObj, customerType);
            }
        }
    }

    @Override
    public OrderDO orderInWarehouse(OrderWarehouseInVO orderWarehouseInVO) {
        // TODO 订单入仓信息录入
        OrderDO orderDO = orderMapper.selectById(orderWarehouseInVO.getOrderId());
        if (Objects.isNull(orderDO)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        // 校验是否有已核销的应收单，如果有，则不能再次入仓修改
        receivableService.verificationReceivableIsWriteOff(orderDO.getOrderId(), null);
        List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderDO.getOrderId()));

        List<OrderItemInWarehouseVO> orderItemInWarehouseVOList =
                orderWarehouseInVO.getOrderItemInWarehouseVOList();

        if (CollectionUtil.isNotEmpty(orderItemInWarehouseVOList) && CollectionUtil.isNotEmpty(orderItemDOList)) {
            orderItemInWarehouseVOList.forEach(vo -> {
                for (OrderItemDO orderItemDO : orderItemDOList) {
                    if (null != vo.getOrderItemId() && Objects.equals(orderItemDO.getOrderItemId(), vo.getOrderItemId()) && Objects.equals(orderItemDO.getProdId(), vo.getProdId())) {
                        if (null != vo.getProdType()) {
                            orderItemDO.setProdType(vo.getProdType());
                        }
                        if (null != vo.getBrandType()) {
                            orderItemDO.setBrandType(vo.getBrandType());
                        }
                        if (StringUtils.isNotBlank(vo.getProdTitleZh())) {
                            orderItemDO.setProdTitleZh(vo.getProdTitleZh());
                        }
                        if (StringUtils.isNotBlank(vo.getProdTitleEn())) {
                            orderItemDO.setProdTitleEn(vo.getProdTitleEn());
                        }
                    }
                }
            });
        }
        OrderConsignorDO orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, orderDO.getOrderId()).last("limit 1"));
        OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, orderDO.getOrderId()).last("limit 1"));
        // 更新所属客户经理(业务员)
        // TODO 2024-08-01 此处为入仓修改，客户归属信息不变的情况下，不再修改客户经理的业绩归属
//        if (Objects.isNull(orderDO.getParentOrderId()) || orderDO.getParentOrderId() == 0 || orderDO.getSplitSeparateOrder()) {
//            // 拆单子订单不执行客户经理分配规则，以原单为主
//            if (Objects.nonNull(orderDO.getCustomerId()) && orderDO.getCustomerId() > 0) {
//                addOrderCustomerService(orderDO, Objects.equals(orderConsignorDO.getCustomerId(), orderDO.getCustomerId()) ? 1 : 2);
//            }
//        }
        orderBusinessService.costCalculation(String.valueOf(SecurityFrameworkUtils.getLoginUserId()), orderDO, orderConsignorDO.getCustomerId(),
                Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerId(), orderConsignorDO.getCustomerContactsId(), Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerContactsId(),
                orderItemDOList, 3);
        return orderDO;
    }


    @Override
    public OrderDO shipmentOrderInWarehouse(OrderWarehouseInVO orderWarehouseInVO) {
        // TODO 订单入仓信息录入
        OrderDO orderDO = orderMapper.selectById(orderWarehouseInVO.getOrderId());
        if (Objects.isNull(orderDO)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        // 校验是否有已核销的应收单，如果有，则不能再次入仓修改
        receivableService.verificationReceivableIsWriteOff(orderDO.getOrderId(), null);
        List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderDO.getOrderId()));

        List<OrderItemInWarehouseVO> orderItemInWarehouseVOList =
                orderWarehouseInVO.getOrderItemInWarehouseVOList();

        if (CollectionUtil.isNotEmpty(orderItemInWarehouseVOList) && CollectionUtil.isNotEmpty(orderItemDOList)) {
            orderItemInWarehouseVOList.forEach(vo -> {
                for (OrderItemDO orderItemDO : orderItemDOList) {
                    if (null != vo.getOrderItemId() && Objects.equals(orderItemDO.getOrderItemId(), vo.getOrderItemId()) && Objects.equals(orderItemDO.getProdId(), vo.getProdId())) {
                        if (null != vo.getProdType()) {
                            orderItemDO.setProdType(vo.getProdType());
                        }
                        if (null != vo.getBrandType()) {
                            orderItemDO.setBrandType(vo.getBrandType());
                        }
                        if (StringUtils.isNotBlank(vo.getProdTitleZh())) {
                            orderItemDO.setProdTitleZh(vo.getProdTitleZh());
                        }
                        if (StringUtils.isNotBlank(vo.getProdTitleEn())) {
                            orderItemDO.setProdTitleEn(vo.getProdTitleEn());
                        }
                    }
                }
            });
        }
        OrderConsignorDO orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, orderDO.getOrderId()).last("limit 1"));
        OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, orderDO.getOrderId()).last("limit 1"));

        orderBusinessService.costCalculation(String.valueOf(SecurityFrameworkUtils.getLoginUserId()), orderDO, orderConsignorDO.getCustomerId(),
                Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerId(), orderConsignorDO.getCustomerContactsId(),
                Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerContactsId(),
                orderItemDOList, 18);
        return orderDO;
    }


    @Override
    public void mergeOrder(@Valid OrderDO orderDO) {
        if (Objects.isNull(orderDO)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        if (StringUtils.isBlank(orderDO.getOldNumbers())) {
            throw exception(MERGE_ORDER_NO_NOT_NULL);
        }
        if (StringUtils.isBlank(orderDO.getOrderNo())) {
            throw exception(ORDER_NO_NOT_NULL);
        }
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        String creator = String.valueOf(orderDO.getCreator() != null ? orderDO.getCreator() : loginUser.getId());
        Date now = new Date();
        orderDO.setUpdater(creator);
        orderDO.setUpdateTime(now);
        if (orderDO.getOrderId() == null || orderDO.getOrderId() <= 0L) {
            orderDO.setCreator(creator);
            orderDO.setCreateTime(now);
            orderMapper.insert(orderDO);
        } else {
            orderMapper.updateById(orderDO);
        }

        // 订单始发地信息
        OrderDepartureDO departureDO = orderDO.getOrderDepartureDO();
        departureDO.setUpdater(creator);
        departureDO.setUpdateTime(now);
        if (departureDO.getId() == null || departureDO.getId() <= 0) {
            departureDO.setCreator(creator);
            departureDO.setCreateTime(now);
            departureDO.setOrderId(orderDO.getOrderId());
            orderDepartureService.save(departureDO);
        } else {
            orderDepartureService.updateById(departureDO);
        }
        // 订单目的地信息
        OrderObjectiveDO objectiveDO = orderDO.getOrderObjectiveDO();
        objectiveDO.setUpdater(creator);
        objectiveDO.setUpdateTime(now);
        if (objectiveDO.getId() == null || objectiveDO.getId() <= 0L) {
            objectiveDO.setCreator(creator);
            objectiveDO.setCreateTime(now);
            objectiveDO.setOrderId(orderDO.getOrderId());
            orderObjectiveService.save(objectiveDO);
        } else {
            orderObjectiveService.updateById(objectiveDO);
        }

        // 订单发货人信息
        OrderConsignorDO consignorDO = orderDO.getOrderConsignorDO();
        consignorDO.setUpdater(creator);
        consignorDO.setUpdateTime(now);
        if (consignorDO.getId() == null || consignorDO.getId() <= 0L) {
            consignorDO.setCreator(creator);
            consignorDO.setCreateTime(now);
            consignorDO.setOrderId(orderDO.getOrderId());
            orderConsignorService.save(consignorDO);
        } else {
            orderConsignorService.updateById(consignorDO);
        }
        // 订单收货人信息
        OrderConsigneeDO consigneeDO = orderDO.getOrderConsigneeDO();
        consigneeDO.setUpdater(creator);
        consigneeDO.setUpdateTime(now);
        if (consigneeDO.getId() == null || consigneeDO.getId() <= 0L) {
            consigneeDO.setCreator(creator);
            consigneeDO.setCreateTime(now);
            consigneeDO.setOrderId(orderDO.getOrderId());
            orderConsigneeService.save(consigneeDO);
        } else {
            orderConsigneeService.updateById(consigneeDO);
        }
        List<OrderItemDO> orderItemDOList = orderDO.getOrderItemDOList();
        // 订单控货人信息
        if (orderDO.getIsCargoControl()) {
            OrderCargoControlDO orderCargoControlDO = orderDO.getOrderCargoControlDO();
            orderCargoControlDO.setUpdater(creator);
            orderCargoControlDO.setUpdateTime(now);
            if (orderCargoControlDO.getId() == null || orderCargoControlDO.getId() <= 0L) {
                orderCargoControlDO.setCreator(creator);
                orderCargoControlDO.setCreateTime(now);
                orderCargoControlDO.setOrderId(orderDO.getOrderId());
                orderCargoControlDO.setOrderNo(orderDO.getOrderNo());
                orderCargoControlMapper.insert(orderCargoControlDO);
            } else {
                orderCargoControlMapper.updateById(orderCargoControlDO);
            }
        } else {
            orderCargoControlMapper.delete(new LambdaQueryWrapper<OrderCargoControlDO>().eq(OrderCargoControlDO::getOrderId, orderDO.getOrderId()));
        }
        // 更新特需
        this.saveOrUpdateSpecialNeed(orderDO.getOrderId(), orderDO.getPackageType(), orderDO.getPackageRemarks(), creator, now);
        // 合单时重新判定订单重泡货类型
        mergeOrderJudgingHeavyFoamGoods(orderDO, orderItemDOList, consignorDO, consigneeDO);

        orderBusinessService.costCalculation(String.valueOf(SecurityFrameworkUtils.getLoginUserId()), orderDO, consignorDO.getCustomerId(), Objects.isNull(consigneeDO) ? 0L : consigneeDO.getCustomerId(),
                consignorDO.getCustomerContactsId(), Objects.isNull(consigneeDO) ? 0L : consigneeDO.getCustomerContactsId(), orderItemDOList, 4);
        boolean isPayAdvanceException = this.addOrderReceivable(orderDO, 1);
//        if (isPayAdvanceException) {
//            List<OrderExceptionDO> orderExceptionDOList = orderExceptionService.getOrderExceptionByOrderIdAndOrderItemIdAndExceptionKey(orderDO.getOrderId(), null, OrderExceptionEnum.ORDER_PAY_EXCEPTION.getKey());
//            log.info("订单【{}】生成预付异常数量：{}", orderDO.getOrderNo(), CollectionUtil.isEmpty(orderExceptionDOList) ? 0 : orderExceptionDOList.size());
//            if (CollectionUtil.isEmpty(orderExceptionDOList)) {
//                log.info("订单【{}】生成预付异常", orderDO.getOrderNo());
//                OrderExceptionCreateReqVO orderExceptionCreateReqVO = this.genOrderException(orderDO.getOrderId(), orderDO, null, OrderExceptionEnum.ORDER_PAY_EXCEPTION,
//                        OrderExceptionEnum.ORDER_PAY_EXCEPTION.getZhValueDesc(), OrderExceptionEnum.ORDER_PAY_EXCEPTION.getEnValueDesc());
//                orderExceptionService.createOrderException(orderExceptionCreateReqVO);
//            }
//        }
        // 对新订单，插入合单成功，待入仓日志
        orderBusinessService.addOrderTimeLog(orderDO.getStatus(), orderDO, 2, now, now);
        // 更新订单操作日志
        orderBusinessService.addOrderOperateLog(orderDO.getOrderId(), "订单合单操作", null);
    }

    private void mergeOrderJudgingHeavyFoamGoods(OrderDO orderDO, List<OrderItemDO> orderItemDOList, OrderConsignorDO consignorDO, OrderConsigneeDO consigneeDO) {
        LogisticsInfoDto logisticsInfoDto = warehouseLineMapper.getStartInfoAndDestInfoByLineId(orderDO.getLineId());
        if (Objects.isNull(logisticsInfoDto)) {
            throw exception(TRANSPORT_LINE_NOT_EXISTS);
        }
        QueryChannelInfoEvent event = new QueryChannelInfoEvent();
        if (Objects.nonNull(orderDO.getChannelId()) && orderDO.getChannelId() > 0) {
            event.setChannelId(orderDO.getChannelId());
            applicationContext.publishEvent(event);
        }
        CustomerZhongPaoQueryVO customerZhongPaoQueryVO = new CustomerZhongPaoQueryVO();
        customerZhongPaoQueryVO.setDepartureId(logisticsInfoDto.getStartCityId());
        customerZhongPaoQueryVO.setObjectiveId(logisticsInfoDto.getDestCityId());
        customerZhongPaoQueryVO.setStartWarehouseId(logisticsInfoDto.getStartWarehouseId());
        customerZhongPaoQueryVO.setDestWarehouseId(logisticsInfoDto.getDestWarehouseId());
        customerZhongPaoQueryVO.setConsignorId(consignorDO.getCustomerId());
        customerZhongPaoQueryVO.setConsigneeId(consigneeDO.getCustomerId());
        // 获取全局重泡货与客户设置重泡货配置综合最优值
        ZhongPaoBestVO zhongPaoBestVO = zhongPaoService.getCustomerBestZhongPao(customerZhongPaoQueryVO);
        // 判断是否需要生成重货异常
        if ((TransportTypeShortEnum.SEA_CONTAINER.getValue().equals(orderDO.getTransportId()) || TransportTypeShortEnum.MARINE_CONTAINER.getValue().equals(orderDO.getTransportId()))) {
            if (zhongPaoBestVO.getZhongEdge() != null && orderDO.getSumWeight() != null) {
                // 计算（入仓总重量/750（取自当前用户的重货标准）>总体积）
                BigDecimal zhongCbm = orderDO.getSumWeight().divide(zhongPaoBestVO.getZhongEdge(), 2, RoundingMode.HALF_UP);
                List<OrderExceptionDO> pendHeavyExceptionList = orderExceptionService.getPendingOrderExceptionByOrderIdAndOrderItemIdAndExceptionKey(orderDO.getOrderId(), null, OrderExceptionEnum.ORDER_HEAVY_CARGO_EXCEPTION.getKey());
                if (zhongCbm.compareTo(orderDO.getSumVolume()) > 0) {
                    // 重货异常
                    String descZh = String.format("该订单是重货订单, 重货方数(总)：%s", zhongCbm);
                    String descEn = String.format("It's heavy order, value(sum)：%s", zhongCbm);
                    if (CollectionUtil.isEmpty(pendHeavyExceptionList) || pendHeavyExceptionList.size() == 0) {
                        OrderExceptionCreateReqVO orderExceptionCreateReqVO = this.genOrderException(orderDO.getOrderId(), orderDO, null, null, OrderExceptionEnum.ORDER_HEAVY_CARGO_EXCEPTION, descZh, descEn);
                        orderExceptionService.createOrderException(orderExceptionCreateReqVO);
                    } else {
                        // 如果有异常则更新说明
                        OrderExceptionDO orderExceptionDO = pendHeavyExceptionList.get(0);
                        orderExceptionDO.setOrderExceptionRemark(JSONObject.toJSONString(OrderExceptionDescVO.builder().descZh(descZh).descEn(descEn).build()));
                        orderExceptionService.updateById(orderExceptionDO);
                    }
                    //更新订单为重货
                    this.updateOrderType(orderDO.getOrderId(), 2);
                } else {
                    //更新订单为普货
                    this.updateOrderType(orderDO.getOrderId(), 1);
                }
            }
        }
        if ((TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue().equals(orderDO.getTransportId()) || TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue().equals(orderDO.getTransportId()))) {
            // 此处订单打包后 判断是否需要生成泡货异常
            if (orderDO.getAirShipment() == 4) {
                if (zhongPaoBestVO.getPaoEdge() != null && orderDO.getSumVolume() != null) {
                    // 计算（入仓总体积*167（取自当前用户的泡货标准）>入仓总重量）
                    BigDecimal paoKg = orderDO.getSumVolume().multiply(zhongPaoBestVO.getPaoEdge());
                    paoKg = BigDecimalUtils.convertWv(paoKg);
                    List<OrderExceptionDO> pendBulkyExceptionList = orderExceptionService.getPendingOrderExceptionByOrderIdAndOrderItemIdAndExceptionKey(orderDO.getOrderId(), null, OrderExceptionEnum.ORDER_BULKY_CARGO_EXCEPTION.getKey());
                    if (paoKg.compareTo(orderDO.getSumWeight()) > 0) {
                        // 泡货异常
                        String descZh = String.format("该订单是泡货订单, 泡货重量(总)：%sKg", paoKg);
                        String descEn = String.format("It's bubble order, weight(sum)：%s", paoKg);
                        if (CollectionUtil.isEmpty(pendBulkyExceptionList) || pendBulkyExceptionList.size() == 0) {
                            OrderExceptionCreateReqVO orderExceptionCreateReqVO = this.genOrderException(orderDO.getOrderId(), orderDO, null, null, OrderExceptionEnum.ORDER_BULKY_CARGO_EXCEPTION, descZh, descEn);
                            orderExceptionService.createOrderException(orderExceptionCreateReqVO);
                        } else {
                            // 如果有异常则更新说明
                            OrderExceptionDO orderExceptionDO = pendBulkyExceptionList.get(0);
                            orderExceptionDO.setOrderExceptionRemark(JSONObject.toJSONString(OrderExceptionDescVO.builder().descZh(descZh).descEn(descEn).build()));
                            orderExceptionService.updateById(orderExceptionDO);
                        }
                        //更新订单为泡货
                        this.updateOrderType(orderDO.getOrderId(), 3);
                    } else {
                        //更新订单为普货
                        this.updateOrderType(orderDO.getOrderId(), 1);
                    }
                }
            }
        }
    }

    @Override
    public OrderDO splitOrder(@Valid OrderDO orderDO, String msg) {
        if (Objects.isNull(orderDO)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        if (StringUtils.isBlank(orderDO.getParentNumber())) {
            throw exception(SPLIT_ORDER_NO_NOT_NULL);
        }
        if (StringUtils.isBlank(orderDO.getOrderNo())) {
            throw exception(ORDER_NO_NOT_NULL);
        }
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        String creator = String.valueOf(loginUser != null ? loginUser.getId() : null);
        // 判断此拆单编号是否存在，已存在则做更新操作
        OrderDO oldOrder = orderMapper.selectOne(new LambdaQueryWrapper<OrderDO>().eq(OrderDO::getOrderNo, orderDO.getOrderNo()));
        Date now = new Date();
        // 订单始发地信息
        OrderDepartureDO departureDO = orderDO.getOrderDepartureDO();
        // 订单目的地信息
        OrderObjectiveDO objectiveDO = orderDO.getOrderObjectiveDO();

        List<OrderTimeDO> parentOrderTimeList = null;
        if (Objects.nonNull(oldOrder)) {
            orderDO.setOrderId(oldOrder.getOrderId());
            // 需要清除订单项数据(包括入仓记录)，进行重新插入
            orderItemMapper.delete(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, oldOrder.getOrderId()));
            orderWarehouseInMapper.delete(new LambdaQueryWrapperX<OrderWarehouseInDO>()
                    .eq(OrderWarehouseInDO::getOrderId, oldOrder.getOrderId()));
        } else {
            if (StringUtils.isEmpty(orderDO.getCreator())) {
                orderDO.setCreator(creator);
            }
            orderDO.setCreateTime(now);
            // 当属于新增的订单id，则需要更新上级订单的订单动态到新订单
            parentOrderTimeList = orderTimeMapper.selectList(new LambdaQueryWrapper<OrderTimeDO>()
                    .eq(OrderTimeDO::getOrderId, orderDO.getParentOrderId())
                    .orderByAsc(OrderTimeDO::getId));
        }
        orderDO.setUpdater(creator);
        orderDO.setUpdateTime(now);
        this.saveOrUpdate(orderDO);
        if (Objects.nonNull(parentOrderTimeList) && CollectionUtil.isNotEmpty(parentOrderTimeList)) {
            // 下单动态在第一个
            OrderTimeDO orderPlaceTimeDO = parentOrderTimeList.get(0);
            if (!orderDO.getIsBoxSplitOrder()) {
                // 非出货拆单，即入仓拆单，主拆单和子拆单都只需要同步下单动态
                orderPlaceTimeDO.setOrderId(orderDO.getOrderId());
                orderPlaceTimeDO.setId(null);
                orderTimeMapper.insert(orderPlaceTimeDO);
            } else {
                // 出货拆单
                // 退场拆单需要继承上级订单的全部动态，装柜拆单只又主拆单需要继承
                if (orderDO.getPartRefundSplit() || (orderDO.getIsMaster() && !orderDO.getPartRefundSplit())) {
                    List<OrderTimeDO> newOrderTimeList = parentOrderTimeList.stream().peek(t -> {
                        t.setId(null);
                        t.setOrderId(orderDO.getOrderId());
                    }).collect(Collectors.toList());
                    orderTimeMapper.insertBatch(newOrderTimeList);
                } else {
                    orderPlaceTimeDO.setOrderId(orderDO.getOrderId());
                    orderPlaceTimeDO.setId(null);
                    orderTimeMapper.insert(orderPlaceTimeDO);
                }
            }
        }
        if (Objects.isNull(oldOrder)) {
            // 如果该订单不是子订单进行拆单(子订单拆单的主拆单订单编号都未变动，所以拆单业务中，只会重置原单的计算应收和特需费用)
            if (orderDO.getIsMaster()) {
                // 主拆单继承父订单的费用申请应收单
                ReceivableQueryVO queryVO = new ReceivableQueryVO();
                queryVO.setOrderId(orderDO.getParentOrderId());
                queryVO.setFeeSource(2);
                List<ReceivableDO> receivableDOList = receivableService.getReceivableList(queryVO);
                Map<Long, Long> receivableIdMap = new HashMap<>(receivableDOList.size());
                if (CollectionUtil.isNotEmpty(receivableDOList)) {
                    for (ReceivableDO r : receivableDOList) {
                        ReceivableDO rd = new ReceivableDO();
                        BeanUtils.copyProperties(r, rd);
                        rd.setId(null);
                        rd.setOrderId(orderDO.getOrderId());
                        rd.setOrderNo(orderDO.getOrderNo());
                        receivableService.save(rd);
                        // 保存原单应收单与当前订单应收单的id键值对
                        receivableIdMap.put(r.getId(), rd.getId());
                    }
                }
                List<OrderFeeApplicationDO> feeApplicationDOList = feeApplicationService.getFeeApplicationListByOrderId(orderDO.getParentOrderId());
                if (CollectionUtil.isNotEmpty(feeApplicationDOList)) {
                    for (OrderFeeApplicationDO f : feeApplicationDOList) {
                        OrderFeeApplicationDO fa = new OrderFeeApplicationDO();
                        BeanUtils.copyProperties(f, fa);
                        fa.setId(null);
                        fa.setOrderId(orderDO.getOrderId());
                        if (Objects.nonNull(f.getReceivableId()) && !receivableIdMap.isEmpty() && Objects.nonNull(receivableIdMap.get(f.getReceivableId().longValue()))) {
                            fa.setReceivableId(receivableIdMap.get(f.getReceivableId().longValue()).intValue());
                        }
                        feeApplicationService.save(fa);
                    }
                }
            }
        }

        // 订单始发地信息
        if (Objects.nonNull(oldOrder)) {
            OrderDepartureDO oldDepartureDO = orderDepartureService.getOne(new LambdaQueryWrapper<OrderDepartureDO>().eq(OrderDepartureDO::getOrderId, oldOrder.getOrderId()).last("limit 1"));
            departureDO.setId(oldDepartureDO.getId());
        } else {
            departureDO.setId(null);
            departureDO.setCreator(creator);
            departureDO.setCreateTime(now);
        }
        departureDO.setOrderId(orderDO.getOrderId());
        departureDO.setUpdater(creator);
        departureDO.setUpdateTime(now);
        orderDepartureService.saveOrUpdate(departureDO);
        // 订单目的地信息
        if (Objects.nonNull(oldOrder)) {
            OrderObjectiveDO oldObjectiveDO = orderObjectiveService.getOne(new LambdaQueryWrapper<OrderObjectiveDO>().eq(OrderObjectiveDO::getOrderId, oldOrder.getOrderId()).last("limit 1"));
            objectiveDO.setId(oldObjectiveDO.getId());
        } else {
            objectiveDO.setId(null);
            objectiveDO.setCreator(creator);
            objectiveDO.setCreateTime(now);
        }
        objectiveDO.setUpdater(creator);
        objectiveDO.setUpdateTime(now);
        objectiveDO.setOrderId(orderDO.getOrderId());
        orderObjectiveService.saveOrUpdate(objectiveDO);

        // 订单发货人信息
        OrderConsignorDO consignorDO = orderDO.getOrderConsignorDO();
        if (Objects.nonNull(oldOrder)) {
            OrderConsignorDO oldConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, oldOrder.getOrderId()).last("limit 1"));
            consignorDO.setId(oldConsignorDO.getId());
        } else {
            consignorDO.setId(null);
            consignorDO.setCreator(creator);
            consignorDO.setCreateTime(now);
        }
        consignorDO.setUpdater(creator);
        consignorDO.setUpdateTime(now);
        consignorDO.setOrderId(orderDO.getOrderId());
        orderConsignorService.saveOrUpdate(consignorDO);
        // 订单收货人信息
        OrderConsigneeDO consigneeDO = orderDO.getOrderConsigneeDO();
        if (Objects.nonNull(oldOrder)) {
            OrderConsigneeDO oldConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, oldOrder.getOrderId()).last("limit 1"));
            consigneeDO.setId(oldConsigneeDO.getId());
        } else {
            consigneeDO.setId(null);
            consigneeDO.setCreator(creator);
            consigneeDO.setCreateTime(now);
        }
        consigneeDO.setUpdater(creator);
        consigneeDO.setUpdateTime(now);
        consigneeDO.setOrderId(orderDO.getOrderId());
        orderConsigneeService.saveOrUpdate(consigneeDO);

        // 订单控货人信息
        if (orderDO.getIsCargoControl()) {
            OrderCargoControlDO orderCargoControlDO = orderDO.getOrderCargoControlDO();
            if (Objects.nonNull(oldOrder)) {
                OrderCargoControlDO oldCargoControlDO = orderCargoControlMapper.selectOne(new LambdaQueryWrapper<OrderCargoControlDO>()
                        .eq(OrderCargoControlDO::getOrderId, oldOrder.getOrderId())
                        .eq(OrderCargoControlDO::getIsActual, true)
                        .last("limit 1"));
                orderCargoControlDO.setId(oldCargoControlDO.getId());
            } else {
                orderCargoControlDO.setId(null);
                orderCargoControlDO.setCreator(creator);
                orderCargoControlDO.setCreateTime(now);
            }
            orderCargoControlDO.setUpdater(creator);
            orderCargoControlDO.setUpdateTime(now);
            orderCargoControlDO.setOrderId(orderDO.getOrderId());
            orderCargoControlDO.setOrderNo(orderDO.getOrderNo());
            if (Objects.nonNull(orderCargoControlDO.getId())) {
                orderCargoControlMapper.updateById(orderCargoControlDO);
            } else {
                orderCargoControlMapper.insert(orderCargoControlDO);
            }
        }
        List<OrderItemDO> orderItemDOList = orderDO.getOrderItemDOList().stream().peek(item -> item.setOrderItemId(null)).collect(Collectors.toList());
        List<ApplyInfoVO> applyInfoVOList = new ArrayList<>();
        for (OrderItemDO orderItemDO : orderItemDOList) {
            if (CollectionUtil.isNotEmpty(orderItemDO.getApplyInfoVOList())) {
                applyInfoVOList.addAll(orderItemDO.getApplyInfoVOList());
            }
        }
        OrderConsignorDO orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, orderDO.getOrderId()).last("limit 1"));
        OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, orderDO.getOrderId()).last("limit 1"));
        orderBusinessService.costCalculation(String.valueOf(SecurityFrameworkUtils.getLoginUserId()), orderDO, orderConsignorDO.getCustomerId(), Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerId(),
                orderConsignorDO.getCustomerContactsId(), Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerContactsId(), orderItemDOList, 5);
        // 更新特需
        this.saveOrUpdateSpecialNeed(orderDO.getOrderId(), orderDO.getPackageType(), orderDO.getPackageRemarks(), creator, now);
        // 对拆出的新订单，插入拆单成功，待入仓日志
        orderBusinessService.addOrderTimeLog(orderDO.getStatus(), orderDO, 1, now, now);
        // 拆单成功更新订单操作日志，添加订单拆单记录描述
        orderBusinessService.addOrderOperateLog(orderDO.getOrderId(), "", msg, applyInfoVOList);
        return orderDO;
    }


    @Override
    public Integer updateStatus(Long orderId, String orderNo, Integer status, Integer abnormalState, Integer
            inWarehouseState, Integer shipmentState, Integer auditType, String auditResult) {
        Date now = new Date();
        return this.updateStatusAndTime(orderId, orderNo, status, abnormalState, inWarehouseState, shipmentState, auditType, auditResult, now, null, null, true, 0);
    }

    @Override
    public Integer updateStatus(Long orderId, String orderNo, Integer status, Integer abnormalState, Integer
            inWarehouseState, Integer shipmentState, Integer auditType, String auditResult, boolean isAddOrderOperateLog) {
        return this.updateStatusAndTime(orderId, orderNo, status, abnormalState, inWarehouseState, shipmentState, auditType, auditResult, new Date(), null, null, false, 0);
    }

    @Override
    public Integer updateStatus(Long orderId, String orderNo, Integer status, Integer abnormalState, Integer
            inWarehouseState, Integer shipmentState, Integer auditType, String auditResult, Date date, boolean flag) {
        if (Objects.isNull(date)) {
            date = new Date();
        }
        return this.updateStatusAndTime(orderId, orderNo, status, abnormalState, inWarehouseState, shipmentState, auditType, auditResult, date, null, null, flag, 0);
    }

    @Override
    public Integer updateStatus(Long orderId, String orderNo, Integer status, Integer abnormalState, Integer inWarehouseState,
                                Integer shipmentState, Integer auditType, String auditResult, Date date, boolean flag, Integer hasExit) {
        if (Objects.isNull(date)) {
            date = new Date();
        }
        return this.updateStatusAndTime(orderId, orderNo, status, abnormalState, inWarehouseState, shipmentState, auditType, auditResult, date, null, null, flag, hasExit);
    }

    @Override
    public Integer updateStatus(Long orderId, String orderNo, Integer status, Integer abnormalState, Integer
            inWarehouseState, Integer shipmentState, Integer auditType, String auditResult, Date date, String type, String note) {
        if (Objects.isNull(date)) {
            date = new Date();
        }
        return this.updateStatusAndTime(orderId, orderNo, status, abnormalState, inWarehouseState, shipmentState, auditType, auditResult, date, type, note, true, 0);
    }

    private Integer updateStatusAndTime(Long orderId, String orderNo, Integer status, Integer
            abnormalState, Integer inWarehouseState, Integer shipmentState, Integer auditType, String auditResult, Date date, String type,
                                        String note, boolean isAddOrderOperateLog, Integer hasExit) {
        OrderDO currentOrderDO;
        if (orderId != null) {
            currentOrderDO = orderMapper.selectById(orderId);
        } else {
            currentOrderDO = orderMapper.selectOne(new LambdaQueryWrapper<OrderDO>().eq(OrderDO::getOrderNo, orderNo).last("limit 1"));
        }
        if (Objects.isNull(currentOrderDO)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        // 需要产生预付异常(预付异常只在入仓时产生, 且只能产生一次)
        boolean isPayAdvanceException = false;
        int result = 0;
        // 根据当前订单主状态更新相应的状态， 异常状态除外
        // 有审批结果，需要更新审批结果
        String msg = "";
        if (Objects.nonNull(status)) {
            if (Objects.equals(OrderStatusEnum.IN_WAREHOUSE.getValue(), status)) {
                // 每次更新已入仓状态的同时，刷新入仓动态
                Long timeId = null;
                Date businessTime = null;
                currentOrderDO.setLastTimeTotalNum(0);
                if (Objects.nonNull(hasExit) && hasExit == 1) {
                    // 部分退场入仓
                    if (Objects.equals(currentOrderDO.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue())) {
                        orderBusinessService.addAirOrderTimeLog(currentOrderDO, OrderAirTimeEnum.AIR_IN_WAREHOUSE, null, null, null, null, null, null);
                    } else if (Objects.equals(currentOrderDO.getTransportId(), TransportTypeShortEnum.SEA_CONTAINER.getValue())) {
                        orderBusinessService.addSeaOrderTimeLog(currentOrderDO, OrderSeaTimeEnum.SEA_IN_WAREHOUSE, null, null, null, null, null, null);
                    }
                } else {
                    List<OrderTimeDO> orderTimeDOS = orderTimeMapper.selectList(new LambdaQueryWrapper<OrderTimeDO>()
                            .eq(OrderTimeDO::getOrderId, currentOrderDO.getOrderId())
                            .eq(OrderTimeDO::getStatus, 520201).orderByDesc(OrderTimeDO::getId));
                    if (CollectionUtil.isNotEmpty(orderTimeDOS) && orderTimeDOS.size() > 0) {
                        OrderTimeDO timeDO = orderTimeDOS.get(0);
                        timeId = timeDO.getId();
                        businessTime = timeDO.getBusinessTime();
                        currentOrderDO.setLastTimeTotalNum(timeDO.getTotalNum());
                    }
                    if (Objects.equals(currentOrderDO.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue())) {
                        orderBusinessService.addAirOrderTimeLog(currentOrderDO, OrderAirTimeEnum.AIR_IN_WAREHOUSE, null, null, null, businessTime, null, timeId);
                    } else if (Objects.equals(currentOrderDO.getTransportId(), TransportTypeShortEnum.SEA_CONTAINER.getValue())) {
                        if (currentOrderDO.getLastTimeTotalNum() != currentOrderDO.getSumNum()) {
                            // 当有入仓箱数变化时才做动态更新
                            orderBusinessService.addSeaOrderTimeLog(currentOrderDO, OrderSeaTimeEnum.SEA_IN_WAREHOUSE, null, null, null, businessTime, null, timeId);
                        }
                    }
                }
            }
            if (!Objects.equals(status, currentOrderDO.getStatus())) {
//                if (Objects.equals(OrderStatusEnum.IN_WAREHOUSE.getValue(), status) && prefixType > 0) {
//                    // 跟新为入仓状态时
//                    addPrefixStatus(currentOrderDO, prefixType);
//                }
                // 封装订单主要状态节点时间
                setOrderStatusTime(status, currentOrderDO, date);
                currentOrderDO.setOldStatus(currentOrderDO.getStatus());
                currentOrderDO.setStatus(status);
                if (Objects.equals(OrderStatusEnum.IN_WAREHOUSE.getValue(), status)) {
                    // 判断此订单是否
                    if (Objects.isNull(currentOrderDO.getRucangTime())) {
                        // 更新入仓状态时，同步更新入仓时间
                        currentOrderDO.setRucangTime(date);
                        // 更新订单下订单项商品的成交(销售)价格定价
                        List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, currentOrderDO.getOrderId()));
                        if (CollectionUtil.isNotEmpty(orderItemDOList)) {
                            orderItemDOList = orderItemDOList.stream().peek(item -> {
                                if (!item.getIsPriced() && item.getOneSeaFreight().compareTo(BigDecimal.ZERO) > 0) {
                                    item.setIsPriced(Boolean.TRUE);
                                }
                            }).collect(Collectors.toList());
                            orderItemMapper.updateBatch(orderItemDOList);
                        }
                    }
                    if (Objects.equals(currentOrderDO.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue())) {
                        // 如果是空运订单，订单状态变更为已入仓，那么检查订单备货状态，如果为默认值0，需要更新为1，以避免部分业务没有调用计价接口，导致空运备货状态未更新
                        if (currentOrderDO.getAirShipment() == 0) {
                            currentOrderDO.setAirShipment(1);
                        }
                    }
                }
                //退仓后，重置订单的已入仓数据
                if (Objects.equals(OrderStatusEnum.WITHDRAWN.getValue(), status) && Objects.equals(OrderWarehouseInStatusEnum.rollback_finished.getValue(), inWarehouseState)) {
                    currentOrderDO.setSumQuantity(0);
                    currentOrderDO.setSumWeight(BigDecimal.ZERO);
                    currentOrderDO.setSumVolume(BigDecimal.ZERO);
                    currentOrderDO.setSumNum(0);
                    // 重置空运可出状态
                    currentOrderDO.setAirShipment(0);
                    // 退仓成功，添加动态
                    if (Objects.equals(currentOrderDO.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue())) {
                        orderBusinessService.addAirOrderTimeLog(currentOrderDO, OrderAirTimeEnum.AIR_WAREHOUSE_WITHDRAWAL, null, null, null, null, null, null);
                    } else if (Objects.equals(currentOrderDO.getTransportId(), TransportTypeShortEnum.SEA_CONTAINER.getValue())) {
                        orderBusinessService.addSeaOrderTimeLog(currentOrderDO, OrderSeaTimeEnum.SEA_WAREHOUSE_WITHDRAWAL, null, null, null, null, null, null);
                    }
                }
                //入仓中，重置订单的已入仓数据
                if (Objects.equals(OrderStatusEnum.WAREHOUSING.getValue(), status) && Objects.equals(OrderWarehouseInStatusEnum.warehousing.getValue(), inWarehouseState)) {
                    // 重置空运可出状态
                    currentOrderDO.setAirShipment(0);
                }
                // 单品退仓完后订单改待入仓，也需要重置订单入仓数据与状态
                if (Objects.equals(OrderStatusEnum.ORDER_PLACED.getValue(), status)) {
                    currentOrderDO.setSumQuantity(0);
                    currentOrderDO.setSumWeight(BigDecimal.ZERO);
                    currentOrderDO.setSumVolume(BigDecimal.ZERO);
                    currentOrderDO.setSumNum(0);
                    // 重置空运可出状态
                    currentOrderDO.setAirShipment(0);
                }
                if (!Objects.equals(currentOrderDO.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue()) && !Objects.equals(currentOrderDO.getTransportId(), TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue())) {
                    msg = OrderStatusEnum.valueOf(status).getNameZh();
                } else {
                    if (!status.equals(OrderStatusEnum.INSTALLED_CABINET.getValue())) {
                        // 空运订单出货报关时因主状态变更产生的操作日志隐藏
                        msg = OrderStatusEnum.valueOf(status).getNameZh();
                    }
                    if (status.equals(OrderStatusEnum.IN_SHIPPING.getValue())) {
                        // 此状态为状态13的空运转义状态，当运输方式为空运时，状态13为已起飞, 订单日志信息单独更新
                        msg = OrderStatusEnum.HAS_TAKEN_OFF.getNameZh();
                    }
                }
                orderBusinessService.addOrderTimeLog(status, currentOrderDO, 0, date);
            }

        }
        if (Objects.nonNull(abnormalState)) {
            currentOrderDO.setAbnormalState(abnormalState);
            List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, currentOrderDO.getOrderId()));
            for (OrderItemDO orderItemDO : orderItemDOList) {
                orderBusinessService.updateItem(orderItemDO);
            }
        }

        if (Objects.nonNull(inWarehouseState)) {

            // 保存当前入仓子状态
            currentOrderDO.setOldInWarehouseState(currentOrderDO.getInWarehouseState());
            // 更新入仓子状态
            currentOrderDO.setInWarehouseState(inWarehouseState);
            if (Objects.equals(OrderWarehouseInStatusEnum.warehouse_finished.getValue(), inWarehouseState)) {
                // 根据订单(保价费)及订单项(运费及清关费)，查询应收单状态，是否需要添加应收
                isPayAdvanceException = this.addOrderReceivable(currentOrderDO, 1);
            }
        }
        if (Objects.nonNull(shipmentState)) {

            // 保存当前出货子状态
            currentOrderDO.setOldShipmentState(currentOrderDO.getShipmentState());
            // 更新出货子状态
            currentOrderDO.setShipmentState(shipmentState);
            if (Objects.equals(OrderStatusMsgEnum.SEALED.getStatus(), currentOrderDO.getStatus()) && Objects.equals(OrderStatusMsgEnum.SEALED.getShipmentState(), shipmentState)) {
                // 封柜时间只能以子状态判断
                currentOrderDO.setLoadTime(date);
            }
            if (!Objects.equals(currentOrderDO.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue()) && !Objects.equals(currentOrderDO.getTransportId(), TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue())) {
                if (Objects.equals(OrderStatusMsgEnum.PRE_INSTALLED.getShipmentState(), shipmentState)) {
                    // 海运订单-根据订单(保价费)及订单项(运费及清关费)，查询应收单状态，是否需要添加应收
                    this.addOrderReceivable(currentOrderDO, 1);
                }
            } else {
                if (Objects.equals(OrderStatusMsgEnum.WAREHOUSED.getShipmentState(), shipmentState)) {
                    // 空运订单-根据订单(保价费)及订单项(运费及清关费)，查询应收单状态，是否需要添加应收
                    this.addOrderReceivable(currentOrderDO, 1);
                }
            }
        }

        if (Objects.nonNull(auditType)) {
            // TODO 这里可能出现并行的审批任务，当结束一个审批任务变更为0时，需要同步查询当前正在进行的其他审批任务
            currentOrderDO.setAuditType(auditType);
            currentOrderDO.setAuditResult(auditResult);
            if (StringUtils.isNotBlank(auditResult)) {
                // 获取固定中文说明描述
                msg = I18nMessage.getZhMessage(auditResult);
            }
            if (auditType == 0) {
                this.checkOrderProcessingApprovalType(currentOrderDO, auditType, auditResult);
            }
        }
        if (currentOrderDO.getAuditType() == 0 && StringUtils.isBlank(currentOrderDO.getAuditResult())) {
            currentOrderDO.setAuditResult("");
        }
        orderMapper.updateById(currentOrderDO);

        // 完成入仓时设置入仓体积和入仓重量
        currentOrderDO = orderMapper.selectById(currentOrderDO.getOrderId());
        if (currentOrderDO.getStatus() <= OrderStatusEnum.IN_WAREHOUSE.getValue()
                && (currentOrderDO.getAirShipment() == null || currentOrderDO.getAirShipment() == 0 || currentOrderDO.getAirShipment() == 1 || currentOrderDO.getAirShipment() == 2)) {
            OrderWarehouseInSumBackVO orderWarehouseInSum = orderWarehouseInMapper.getOrderWarehouseInSum(orderId);
            if (orderWarehouseInSum != null) {
                currentOrderDO.setSumWeightFinishedWarehouseIn(orderWarehouseInSum.getSumWeightFinishedWarehouseIn() == null ? BigDecimal.ZERO : orderWarehouseInSum.getSumWeightFinishedWarehouseIn());
                currentOrderDO.setSumVolumeFinishedWarehouseIn(orderWarehouseInSum.getSumVolumeFinishedWarehouseIn() == null ? BigDecimal.ZERO : orderWarehouseInSum.getSumVolumeFinishedWarehouseIn());
                currentOrderDO.setSumCartonsNumFinishedWarehouseIn(orderWarehouseInSum.getSumCartonsNumFinishedWarehouseIn() == null ? 0 : orderWarehouseInSum.getSumCartonsNumFinishedWarehouseIn());
                currentOrderDO.setSumQuantityAllFinishedWarehouseIn(orderWarehouseInSum.getSumQuantityAllFinishedWarehouseIn() == null ? 0 : orderWarehouseInSum.getSumQuantityAllFinishedWarehouseIn());
                orderMapper.update(null, new LambdaUpdateWrapper<OrderDO>()
                        .set(OrderDO::getSumWeightFinishedWarehouseIn, orderWarehouseInSum.getSumWeightFinishedWarehouseIn())
                        .set(OrderDO::getSumVolumeFinishedWarehouseIn, orderWarehouseInSum.getSumVolumeFinishedWarehouseIn())
                        .set(OrderDO::getSumCartonsNumFinishedWarehouseIn, orderWarehouseInSum.getSumCartonsNumFinishedWarehouseIn())
                        .set(OrderDO::getSumQuantityAllFinishedWarehouseIn, orderWarehouseInSum.getSumQuantityAllFinishedWarehouseIn())
                        .eq(OrderDO::getOrderId, currentOrderDO.getOrderId()));
            }
        }

        if (Objects.nonNull(status) || Objects.nonNull(abnormalState) || Objects.nonNull(auditType)) {
            // 如果有异常、审批、主订单状态变更，需要更新关联此订单的主订单关联状态
            updateGuanlianOrderStatus(currentOrderDO);
        }

        if (Objects.nonNull(abnormalState) && abnormalState == 0) {
            if (Objects.equals(currentOrderDO.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue()) || Objects.equals(currentOrderDO.getTransportId(), TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue())) {
                // 如果订单异常处理完成，则更新计价
                handleException(orderId, currentOrderDO, 40);
                // 完成计价业务后，这里需要重新获取最新的订单信息
                currentOrderDO = orderMapper.selectById(orderId);
            }
        }
        // 重置异常提醒
        orderBusinessService.handleOrderRemindException(currentOrderDO.getOrderId(), null);
        if (isPayAdvanceException) {
            result = 1;
        }
        if (StringUtils.isNotBlank(msg) && isAddOrderOperateLog) {
            // 更新订单操作日志
            orderBusinessService.addOrderOperateLog(currentOrderDO.getOrderId(), type, msg, note);
        }
        return result;
    }

    /**
     * 订单审批更新
     *
     * @param orderDO     订单信息
     * @param auditType   审批类型
     * @param auditResult 审批结果
     */
    private void checkOrderProcessingApprovalType(OrderDO orderDO, Integer auditType, String auditResult) {
        // 出货审批更新
        if (StringUtils.isNotBlank(orderDO.getContainerNumber())) {
            BoxCheckOrderApprovalEvent boxCheckOrderApprovalEvent = new BoxCheckOrderApprovalEvent(orderDO.getOrderId(), orderDO.getContainerNumber(), auditType, auditResult, false);
            applicationContext.publishEvent(boxCheckOrderApprovalEvent);
            if (boxCheckOrderApprovalEvent.getIsExists()) {
                orderDO.setAuditType(auditType);
                orderDO.setAuditResult(auditResult);
                return;
            }
        }
        // 入仓审批更新
        OrderWarehouseApprovalDO warehouseApprovalDO = orderWarehouseApprovalService.getOne(new LambdaQueryWrapper<OrderWarehouseApprovalDO>()
                .eq(OrderWarehouseApprovalDO::getOrderIds, orderDO.getOrderId())
                .eq(OrderWarehouseApprovalDO::getStatus, 1)
                .orderByDesc(OrderWarehouseApprovalDO::getId)
                .last("limit 1"));
        if (Objects.nonNull(warehouseApprovalDO)) {
            switch (warehouseApprovalDO.getType()) {
                case 1:
                    // 入仓修改
                    orderDO.setAuditType(warehouse_update_processing.getType());
                    orderDO.setAuditResult(warehouse_update_processing.getDesc());
                    return;
                case 2:
                    // 调仓
                    orderDO.setAuditType(warehouse_adjust_processing.getType());
                    orderDO.setAuditResult(warehouse_adjust_processing.getDesc());
                    return;
                case 3:
                    // 退仓
                    orderDO.setAuditType(warehouse_rollback_processing.getType());
                    orderDO.setAuditResult(warehouse_rollback_processing.getDesc());
                    return;
            }
        }
        // 订单审批更新
        OrderApprovalDO approvalDO = orderApprovalService.getOne(new LambdaQueryWrapper<OrderApprovalDO>()
                .eq(OrderApprovalDO::getOrderId, orderDO.getOrderId())
                .eq(OrderApprovalDO::getStatus, 1)
                .orderByDesc(OrderApprovalDO::getOrderApprovalId)
                .last("limit 1"));
        if (Objects.nonNull(approvalDO)) {
            OrderApprovalTypeResultEnum resultEnum = OrderApprovalTypeResultEnum.typeAndResultOf(approvalDO.getType(), approvalDO.getStatus());
            orderDO.setAuditType(resultEnum.getType());
            orderDO.setAuditResult(resultEnum.getDesc());
        }
    }

    private void addPrefixStatus(OrderDO currentOrderDO, Integer prefixType) {
        String prefixStatusZh = "";
        String prefixStatusEn = "";
        switch (prefixType) {
            case 1:
                prefixStatusZh = "预装移除,";
                prefixStatusEn = "Pre installation removal,";
                break;
            case 2:
                prefixStatusZh = "理货移除,";
                prefixStatusEn = "Tallying removal,";
                break;
            case 3:
                prefixStatusZh = "装柜移除,";
                prefixStatusEn = "Cabinet removal,";
                break;
            case 4:
                prefixStatusZh = "撤销拆单,";
                prefixStatusEn = "Revoke split order,";
                break;
            default:
                break;
        }
//        if (currentOrderDO.getStatus() == OrderStatusEnum.PRE_INSTALLED.getValue()) {
//            prefixStatusZh = "预装移除,";
//            prefixStatusEn = "Pre installation removal,";
//        }
//        if (Objects.equals(currentOrderDO.getStatus(), OrderStatusEnum.INSTALLED_CABINET.getValue())) {
//            prefixStatusZh = "装柜移除,";
//            prefixStatusEn = "Cabinet removal,";
//        }
//        if (currentOrderDO.getShipmentState() == OrderStatusMsgEnum.IN_THE_CABINETS.getShipmentState()) {
//            prefixStatusZh = "理货移除,";
//            prefixStatusEn = "Tallying removal,";
//        }
//        if (Objects.equals(currentOrderDO.getStatus(), OrderStatusEnum.SPLIT_ORDER.getValue())) {
//            prefixStatusZh = "撤销拆单,";
//            prefixStatusEn = "Revoke split order,";
//        }
        currentOrderDO.setPrefixStatusZh(prefixStatusZh);
        currentOrderDO.setPrefixStatusEn(prefixStatusEn);
    }

    @Override
    public void cancelGuanlianOrderStatus(Long orderId, Long relateOrderId) {
        // 获取订单的上级关联订单
        List<OrderDO> orderDOList = new ArrayList<>();
        OrderDO subordinateOrderDO = orderMapper.selectById(relateOrderId);
        OrderDO currentOrderDO = orderMapper.selectById(orderId);
        if (currentOrderDO != null) {
            orderDOList.add(currentOrderDO);
        }
        orderGuanlianService.getGuanlianOrderByRelateOrderId(orderId, orderDOList);
        if (CollectionUtil.isNotEmpty(orderDOList)) {
            // 当出现循环调用时，屏蔽掉当前处理订单为上级订单的数据
            List<GuanLianOrderStatusVO> subordinateGuanLianOrderStatusVOList = new ArrayList<>();
            if (StringUtils.isNotBlank(subordinateOrderDO.getGuanLianOrderStatus())) {
                subordinateGuanLianOrderStatusVOList = JSONArray.parseArray(subordinateOrderDO.getGuanLianOrderStatus(), GuanLianOrderStatusVO.class);
            }
            for (OrderDO orderDO : orderDOList) {
                List<GuanLianOrderStatusVO> guanLianOrderStatusVOList = new ArrayList<>();
                if (StringUtils.isNotBlank(orderDO.getGuanLianOrderStatus())) {
                    guanLianOrderStatusVOList = JSONArray.parseArray(orderDO.getGuanLianOrderStatus(), GuanLianOrderStatusVO.class);
                }
                if (CollectionUtil.isNotEmpty(subordinateGuanLianOrderStatusVOList)) {
                    // 如果当前订单的关联异常信息存在，则需要同步处理
                    // 当前订单的管理异常订单数据需要和上级对比，如果有重复的需要去重，以保证当前订单关联单下级订单的状态能持续向上同步
                    if (CollectionUtil.isNotEmpty(guanLianOrderStatusVOList)) {
                        for (GuanLianOrderStatusVO subordinateGuanLianOrderStatusVO : subordinateGuanLianOrderStatusVOList) {
                            GuanLianOrderStatusVO vo = guanLianOrderStatusVOList.stream()
                                    .filter(order -> Objects.equals(order.getOrderId(), subordinateGuanLianOrderStatusVO.getOrderId()) && Objects.equals(order.getType(), subordinateGuanLianOrderStatusVO.getType()))
                                    .findFirst().orElse(null);
                            if (Objects.nonNull(vo)) {
                                // 如果存在相同的则删除，最后会将当前订单的下级关联异常信息全部同步到上级订单
                                guanLianOrderStatusVOList.remove(vo);
                            }
                        }
                    }
                }
                GuanLianOrderStatusVO statusVO = guanLianOrderStatusVOList.stream().filter(order -> Objects.equals(order.getOrderId(), relateOrderId) && order.getType() == 3).findFirst().orElse(null);
                GuanLianOrderStatusVO auditVO = guanLianOrderStatusVOList.stream().filter(order -> Objects.equals(order.getOrderId(), relateOrderId) && order.getType() == 2).findFirst().orElse(null);
                GuanLianOrderStatusVO abnormalStateVO = guanLianOrderStatusVOList.stream().filter(order -> Objects.equals(order.getOrderId(), relateOrderId) && order.getType() == 1).findFirst().orElse(null);
                // 如果没有关联未入仓状态，则校验是否已经存在该关联未入仓状态，有则删除关联未入仓状态
                if (Objects.nonNull(statusVO)) {
                    guanLianOrderStatusVOList.remove(statusVO);
                }
                // 如果没有关联审批状态，则校验是否已经存在该关联审批状态，有则删除关联审批状态
                if (Objects.nonNull(auditVO)) {
                    guanLianOrderStatusVOList.remove(auditVO);
                }
                // 如果没有关联审批状态，则校验是否已经存在该关联审批状态，否则删除关联审批状态
                if (Objects.nonNull(abnormalStateVO)) {
                    guanLianOrderStatusVOList.remove(abnormalStateVO);
                }
                orderDO.setGuanLianOrderStatus(JSONObject.toJSONString(guanLianOrderStatusVOList));
            }
            // 批量更新上级关联订单的关联异常
            this.updateBatch(orderDOList);
        }
    }

    @Override
    public void updateGuanlianOrderStatus(OrderDO currentOrderDO) {
        // 获取订单的上级关联订单
        List<OrderDO> orderDOList = new ArrayList<>();
        orderDOList.add(currentOrderDO);
        orderGuanlianService.getGuanlianOrderByRelateOrderId(currentOrderDO.getOrderId(), orderDOList);
        List<GuanLianOrderStatusVO> allGuanLianOrderStatusVOList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(orderDOList)) {
            // 所有订单的关联异常状态统计
            for (OrderDO orderDO : orderDOList) {
                // 处理关联未入仓状态
                if (Objects.nonNull(orderDO.getStatus()) && !Objects.equals(orderDO.getStatus(), OrderStatusEnum.CANCEL.getValue()) && orderDO.getStatus() < OrderStatusEnum.IN_WAREHOUSE.getValue()) {
                    // 如果有关联未入仓状态，则校验是否已经存在该关联未入仓状态，不存在则添加，已存在则跳过
                    GuanLianOrderStatusVO statusVO = new GuanLianOrderStatusVO();
                    statusVO.setType(3);
                    statusVO.setOrderId(orderDO.getOrderId());
                    statusVO.setOrderNo(orderDO.getOrderNo());
                    // 关联未入仓状态
                    statusVO.setStatusMsg("guanlian.order.not.in.warehouse");
                    allGuanLianOrderStatusVOList.add(statusVO);
                }
                // 处理关联审核状态
                if (Objects.nonNull(orderDO.getAuditType()) && orderDO.getAuditType() > 0) {
                    // 如果有关联审批状态，则校验是否已经存在该关联审批状态，不存在则添加，已存在则跳过
                    GuanLianOrderStatusVO auditVO = new GuanLianOrderStatusVO();
                    auditVO.setType(2);
                    auditVO.setOrderId(orderDO.getOrderId());
                    auditVO.setOrderNo(orderDO.getOrderNo());
                    // 关联审批状态
                    auditVO.setStatusMsg(OrderApprovalTypeResultEnum.typeAndResultOf(orderDO.getAuditType(), 1).getDesc());
                    allGuanLianOrderStatusVOList.add(auditVO);
                }

                // 处理关联异常状态
                if (Objects.nonNull(orderDO.getAbnormalState()) && orderDO.getAbnormalState() > 0) {
                    // 如果有关联异常状态，则校验是否已经存在该关联异常状态，不存在则添加，已存在重新更新，因为异常状态可以累加更新，单个异常变多个异常
                    GuanLianOrderStatusVO abnormalStateVO = new GuanLianOrderStatusVO();
                    abnormalStateVO.setType(1);
                    abnormalStateVO.setOrderId(orderDO.getOrderId());
                    abnormalStateVO.setOrderNo(orderDO.getOrderNo());
                    // 关联审批状态
                    abnormalStateVO.setStatusMsg(OrderAbnormalStateEnum.valueOf(orderDO.getAbnormalState()).getDesc());
                    allGuanLianOrderStatusVOList.add(abnormalStateVO);
                }
            }
        }
        if (CollectionUtil.isNotEmpty(orderDOList)) {
            for (OrderDO orderDO : orderDOList) {
                // 排除订单自己的关联异常信息，保存剩下的值
                List<GuanLianOrderStatusVO> guanLianOrderStatusVOList = allGuanLianOrderStatusVOList.stream().filter(order -> !Objects.equals(order.getOrderId(), orderDO.getOrderId())).collect(Collectors.toList());
                if (Objects.isNull(guanLianOrderStatusVOList)) {
                    // 如果为null，无法使用插件代码将null值更新到数据库，需要定义空数组来更新
                    guanLianOrderStatusVOList = new ArrayList<>();
                }
                orderDO.setGuanLianOrderStatus(JSONObject.toJSONString(guanLianOrderStatusVOList));
            }
        }
        if (CollectionUtil.isNotEmpty(orderDOList)) {
            this.updateBatchById(orderDOList);
        }
    }

    private void setOrderStatusTime(Integer status, OrderDO currentOrderDO, Date now) {
        switch (OrderStatusEnum.valueOf(status)) {
//            case IN_WAREHOUSE:
//                if (Objects.isNull(currentOrderDO.getRucangTime())) {
//                currentOrderDO.setRucangTime(now);
//                }
//                break;
            case SPLIT_ORDER:
//                if (Objects.isNull(currentOrderDO.getSplitTime())) {
                currentOrderDO.setSplitTime(now);
//                }
                break;
            case CLEARED:
                if (Objects.isNull(currentOrderDO.getQingguanTime())) {
                    currentOrderDO.setQingguanTime(now);
                }
                break;
            case PRE_INSTALLED:
//                if (Objects.isNull(currentOrderDO.getPreLoadTime())) {
                currentOrderDO.setPreLoadTime(now);
//                }
                break;
//            case INSTALLED_CABINET:
//                if (Objects.isNull(currentOrderDO.getLoadTime())) {
//                currentOrderDO.setLoadTime(now);
//                }
//                break;
            case ARRIVED:
//                if (Objects.isNull(currentOrderDO.getDaogangTime())) {
                currentOrderDO.setDaogangTime(now);
//                }
                break;
//            case UNLOADED_CABINET:
//                if (Objects.isNull(currentOrderDO.getUnloadTime())) {
//                currentOrderDO.setUnloadTime(now);
//                }
//                break;
//            case UNLOADED_CABINET_AIR:
//                if (Objects.isNull(currentOrderDO.getUnloadTime())) {
//                currentOrderDO.setUnloadTime(now);
//                }
//                break;
            case PICKED_UP:
//                if (Objects.isNull(currentOrderDO.getTakeTime())) {
                currentOrderDO.setTakeTime(now);
//                }
                break;
            case PART_PICKED_UP:
//                if (Objects.isNull(currentOrderDO.getTakeTime())) {
                currentOrderDO.setTakeTime(now);
//                }
                break;
            default:
                break;
        }
    }

    /**
     * 生成或修改订单信息的应收单
     *
     * @param orderDO 当前订单信息
     * @param type    1 生成应收 2 修改价格时同步更新应收(未生成应收不予执行)
     */
    private boolean addOrderReceivable(OrderDO orderDO, Integer type) {
        boolean isPayAdvanceException = false;
        // 查询订单已添加的费用类型
        List<ReceivableDO> receivableDOList = receivableService.list(new LambdaQueryWrapper<ReceivableDO>().eq(ReceivableDO::getOrderId, orderDO.getOrderId()).eq(ReceivableDO::getDeleted, false));
        // TODO 处理订单项
        CostVO costVO = JSONObject.parseObject(orderDO.getCost(), CostVO.class);
        FeeDto premiumFeeDto = null;
        FeeDto worthFeeDto = null;
        if (Objects.nonNull(costVO)) {
            List<FeeDto> feeDtoList = costVO.getFeeDtoList();
            if (CollectionUtil.isNotEmpty(feeDtoList)) {
                premiumFeeDto = costVO.getFeeDtoList().stream().filter(fee -> Objects.equals(fee.getFeeType(), FeeTypeEnum.INSURANCE_FEE.getType())).findFirst().orElse(null);
                worthFeeDto = costVO.getFeeDtoList().stream().filter(fee -> Objects.equals(fee.getFeeType(), FeeTypeEnum.WORTH.getType())).findFirst().orElse(null);
            }
        }
        List<OrderItemDO> itemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderDO.getOrderId()));
        if (CollectionUtil.isNotEmpty(receivableDOList)) {
            // TODO 处理保价费
            ReceivableDO premiumReceivable = receivableDOList.stream().filter(r -> r.getFeeType() == 6 && Objects.nonNull(r.getFeeSource()) && 1 == r.getFeeSource()).findFirst().orElse(null);
            if (Objects.isNull(premiumReceivable)) {
                if (type == 1) {
                    ReceivableCreateReqVO reqVO = new ReceivableCreateReqVO();
                    reqVO.setOrderId(orderDO.getOrderId());
                    reqVO.setOrderNo(orderDO.getOrderNo());
                    reqVO.setTitleZh(null);
                    reqVO.setTitleEn(null);
                    reqVO.setPaymentUser(String.valueOf(orderDO.getDrawee() != 3 ? orderDO.getDrawee() : orderQueryService.customDrawee(orderDO, 6)));
                    reqVO.setIsPayAdvance(0);
                    reqVO.setCollectionType(4);// 到付
                    reqVO.setFeeType(6);
                    reqVO.setFeeSource(1);
                    if (Objects.nonNull(premiumFeeDto)) {
                        reqVO.setAmountWorth(Objects.isNull(worthFeeDto) ? BigDecimal.ZERO : worthFeeDto.getAmount());
                        reqVO.setUnitPrice(premiumFeeDto.getAmount().setScale(0, RoundingMode.HALF_UP));
                        reqVO.setTotalAmount(premiumFeeDto.getAmount().setScale(0, RoundingMode.HALF_UP));
                        reqVO.setTaxAmount(premiumFeeDto.getAmount().setScale(0, RoundingMode.HALF_UP));
                        reqVO.setCurrencyId(Long.valueOf(premiumFeeDto.getCurrencyId()));
                        receivableService.createReceivable(reqVO);
                    }
                }
            } else {
                // TODO 已经付款的应收单不允许修改
                if (Objects.nonNull(premiumFeeDto) && premiumReceivable.getState() == 0) {
                    premiumReceivable.setTitleZh(null);
                    premiumReceivable.setTitleEn(null);
                    premiumReceivable.setPaymentUser(String.valueOf(orderDO.getDrawee() != 3 ? orderDO.getDrawee() : orderQueryService.customDrawee(orderDO, 6)));
                    premiumReceivable.setAmountWorth(Objects.isNull(worthFeeDto) ? BigDecimal.ZERO : worthFeeDto.getAmount());
                    premiumReceivable.setUnitPrice(premiumFeeDto.getAmount().setScale(0, RoundingMode.HALF_UP));
                    premiumReceivable.setTotalAmount(premiumFeeDto.getAmount().setScale(0, RoundingMode.HALF_UP));
                    premiumReceivable.setTaxAmount(premiumFeeDto.getAmount().setScale(0, RoundingMode.HALF_UP));
                    premiumReceivable.setCurrencyId(Long.valueOf(premiumFeeDto.getCurrencyId()));
                    premiumReceivable.setFeeSource(1);
                    try {
                        receivableService.updateReceivableById(premiumReceivable);
                    } catch (Exception e) {
                        log.error(String.format("订单号[%s]的保价费应收单更新失败，失败原因:%s", orderDO.getOrderNo(), e.getMessage()));
                    }
                }
            }

            if (CollectionUtil.isNotEmpty(itemDOList)) {
                for (OrderItemDO orderItemDO : itemDOList) {

                    if (Objects.isNull(orderItemDO.getWarehouseInInfoVO()) || orderItemDO.getWarehouseInInfoVO().getCartonsNum() == 0) {
                        continue;
                    }

                    ReceivableDO freightReceivable = receivableDOList.stream().filter(r -> r.getFeeType() == 1 && Objects.nonNull(r.getFeeSource())
                            && 1 == r.getFeeSource() && Objects.equals(r.getOrderItemId(), orderItemDO.getOrderItemId())).findFirst().orElse(null);
                    // 运费
                    if (Objects.isNull(freightReceivable)) {
                        if (type == 1) {
                            // 未生成应收时，根据预付状态判断当前订单状态是否生成应收单
                            if (Objects.nonNull(orderItemDO.getIsPayAdvance()) && orderItemDO.getIsPayAdvance() == 1) {
                                if (!Objects.equals(orderDO.getInWarehouseState(), OrderWarehouseInStatusEnum.warehouse_finished.getValue())
                                        && orderDO.getShipmentState() == 0
                                        && Objects.nonNull(orderItemDO.getWarehouseInInfoVO())
                                        && orderItemDO.getWarehouseInInfoVO().getCartonsNum() > 0) {
                                    continue;
                                }
                                isPayAdvanceException = true;
                            } else {
                                if (!Objects.equals(orderDO.getShipmentState(), OrderStatusMsgEnum.PRE_INSTALLED.getShipmentState()) && !Objects.equals(orderDO.getShipmentState(), OrderStatusMsgEnum.WAREHOUSED.getShipmentState())) {
                                    continue;
                                }
                            }
                            this.createReceivable(orderDO, orderItemDO, 1, orderItemDO.getOneSeaFreight(), orderItemDO.getSeaFreight(), orderItemDO.getSeaFreightCurrency());
                        }
                    } else {
                        if (freightReceivable.getState() == 0) {
                            freightReceivable.setTitleZh(orderItemDO.getProdTitleZh());
                            freightReceivable.setTitleEn(orderItemDO.getProdTitleEn());
                            freightReceivable.setIsPayAdvance(orderItemDO.getIsPayAdvance());
                            freightReceivable.setCollectionType(Objects.isNull(orderItemDO.getIsPayAdvance()) || orderItemDO.getIsPayAdvance() == 0 ? 4 : 1);
                            freightReceivable.setPaymentUser(String.valueOf(orderDO.getDrawee() != 3 ? orderDO.getDrawee() : orderQueryService.customDrawee(orderDO, 1)));
                            freightReceivable.setAmountWorth(orderItemDO.getWorth());
                            freightReceivable.setUnitPrice(orderItemDO.getOneSeaFreight());
                            freightReceivable.setTotalAmount(orderItemDO.getSeaFreight().setScale(0, RoundingMode.HALF_UP));
                            freightReceivable.setTaxAmount(orderItemDO.getSeaFreight().setScale(0, RoundingMode.HALF_UP));
                            freightReceivable.setFeeSource(1);
                            if (Objects.isNull(orderItemDO.getWarehouseInInfoVO()) || orderItemDO.getWarehouseInInfoVO().getCartonsNum() == 0) {
                                continue;
                            } else {
                                freightReceivable.setNum(orderItemDO.getWarehouseInInfoVO().getCartonsNum());
                                freightReceivable.setQuantity(orderItemDO.getChargeQuantity().compareTo(orderItemDO.getMinMeteringQuantity()) > 0 ? orderItemDO.getChargeQuantity().intValue() : orderItemDO.getMinMeteringQuantity().intValue());
                                freightReceivable.setWeight(orderItemDO.getChargeWeight().compareTo(orderItemDO.getMinMeteringWeight()) > 0 ? orderItemDO.getChargeWeight() : orderItemDO.getMinMeteringWeight());
                                freightReceivable.setVolume(orderItemDO.getChargeVolume().compareTo(orderItemDO.getMinMeteringVolume()) > 0 ? orderItemDO.getChargeVolume() : orderItemDO.getMinMeteringVolume());
                            }
                            freightReceivable.setCurrencyId(Long.valueOf(orderItemDO.getSeaFreightCurrency()));
                            try {
                                receivableService.updateReceivableById(freightReceivable);
                                if (orderItemDO.getIsPayAdvance() == 1) {
                                    isPayAdvanceException = true;
                                }
                            } catch (Exception e) {
                                log.error(String.format("商品[%s],订单项ID[%s]的运费应收单更新失败，失败原因:%s", freightReceivable.getTitleZh(), freightReceivable.getOrderItemId(), e.getMessage()));
                            }
                        }
                    }
                    ReceivableDO clearanceFeeReceivable = receivableDOList.stream().filter(r -> r.getFeeType() == 2 &&
                            Objects.nonNull(r.getFeeSource()) && 1 == r.getFeeSource() && Objects.equals(r.getOrderItemId(),
                            orderItemDO.getOrderItemId())).findFirst().orElse(null);
                    if (orderItemDO.getCharging() == 0) {
                        // 清关费
                        if (Objects.isNull(clearanceFeeReceivable)) {
                            if (type == 1) {
                                // 未生成应收时，根据预付状态判断当前订单状态是否生成应收单
                                if (Objects.nonNull(orderItemDO.getIsPayAdvance()) && orderItemDO.getIsPayAdvance() == 1) {
                                    if (!Objects.equals(orderDO.getInWarehouseState(), OrderWarehouseInStatusEnum.warehouse_finished.getValue()) &&
                                            orderDO.getShipmentState() == 0 &&
                                            Objects.nonNull(orderItemDO.getWarehouseInInfoVO()) &&
                                            orderItemDO.getWarehouseInInfoVO().getCartonsNum() > 0) {
                                        continue;
                                    }
                                    isPayAdvanceException = true;
                                } else {
                                    if (!Objects.equals(orderDO.getShipmentState(), OrderStatusMsgEnum.PRE_INSTALLED.getShipmentState()) && !Objects.equals(orderDO.getShipmentState(), OrderStatusMsgEnum.WAREHOUSED.getShipmentState())) {
                                        continue;
                                    }
                                }
                                this.createReceivable(orderDO, orderItemDO, 2, orderItemDO.getOneClearanceFreight(), orderItemDO.getClearanceFreight(), orderItemDO.getClearanceFreightCurrency());
                            }
                        } else {
                            if (clearanceFeeReceivable.getState() != 2) {
                                clearanceFeeReceivable.setTitleZh(orderItemDO.getProdTitleZh());
                                clearanceFeeReceivable.setTitleEn(orderItemDO.getProdTitleEn());
                                clearanceFeeReceivable.setIsPayAdvance(orderItemDO.getIsPayAdvance());
                                clearanceFeeReceivable.setCollectionType(Objects.isNull(orderItemDO.getIsPayAdvance()) || orderItemDO.getIsPayAdvance() == 0 ? 4 : 1);
                                clearanceFeeReceivable.setFeeSource(1);
                                clearanceFeeReceivable.setPaymentUser(String.valueOf(orderDO.getDrawee() != 3 ? orderDO.getDrawee() : orderQueryService.customDrawee(orderDO, 2)));
                                if (Objects.isNull(orderItemDO.getWarehouseInInfoVO()) || orderItemDO.getWarehouseInInfoVO().getCartonsNum() == 0) {
                                    continue;
                                } else {
                                    clearanceFeeReceivable.setNum(orderItemDO.getWarehouseInInfoVO().getCartonsNum());
                                    if (orderItemDO.getTransportId() == 1 || orderItemDO.getTransportId() == 2) {
                                        clearanceFeeReceivable.setQuantity(orderItemDO.getChargeQuantity().compareTo(orderItemDO.getMinMeteringQuantity()) > 0 ? orderItemDO.getChargeQuantity().intValue() : orderItemDO.getMinMeteringQuantity().intValue());
                                        clearanceFeeReceivable.setWeight(orderItemDO.getChargeWeight().compareTo(orderItemDO.getMinMeteringWeight()) > 0 ? orderItemDO.getChargeWeight() : orderItemDO.getMinMeteringWeight());
                                        clearanceFeeReceivable.setVolume(orderItemDO.getChargeVolume().compareTo(orderItemDO.getMinMeteringVolume()) > 0 ? orderItemDO.getChargeVolume() : orderItemDO.getMinMeteringVolume());
                                    } else {
                                        // 空运清关费按实际入仓数据来计费
                                        Integer quantityAll = orderItemDO.getWarehouseInInfoVO().getQuantityAll();
                                        clearanceFeeReceivable.setQuantity((Objects.isNull(quantityAll) ? BigDecimal.ZERO : new BigDecimal(quantityAll)).compareTo(orderItemDO.getMinMeteringQuantity()) > 0 ? quantityAll : orderItemDO.getMinMeteringQuantity().intValue());
                                        clearanceFeeReceivable.setWeight(orderItemDO.getWarehouseInInfoVO().getWeight().compareTo(orderItemDO.getMinMeteringWeight()) > 0 ? orderItemDO.getWarehouseInInfoVO().getWeight() : orderItemDO.getMinMeteringWeight());
                                        clearanceFeeReceivable.setVolume(orderItemDO.getWarehouseInInfoVO().getVolume().compareTo(orderItemDO.getMinMeteringVolume()) > 0 ? orderItemDO.getWarehouseInInfoVO().getVolume() : orderItemDO.getMinMeteringVolume());
                                    }
                                }
                                clearanceFeeReceivable.setAmountWorth(orderItemDO.getWorth());
                                clearanceFeeReceivable.setUnitPrice(orderItemDO.getOneClearanceFreight());
                                clearanceFeeReceivable.setTotalAmount(orderItemDO.getClearanceFreight().setScale(0, RoundingMode.HALF_UP));
                                clearanceFeeReceivable.setTaxAmount(orderItemDO.getClearanceFreight().setScale(0, RoundingMode.HALF_UP));
                                clearanceFeeReceivable.setCurrencyId(Long.valueOf(orderItemDO.getClearanceFreightCurrency()));
                                try {
                                    receivableService.updateReceivableById(clearanceFeeReceivable);
                                } catch (Exception e) {
                                    log.error(String.format("商品[%s],订单项ID[%s]的清关费应收单更新失败，失败原因:%s", clearanceFeeReceivable.getTitleZh(), clearanceFeeReceivable.getOrderItemId(), e.getMessage()));
                                }
                            }
                        }
                    } else {
                        // TODO 全价时 对于以存在的清关费未生成应收单的应收需要数据清除
                        if (Objects.nonNull(clearanceFeeReceivable)) {
                            receivableService.update(new LambdaUpdateWrapper<ReceivableDO>().set(ReceivableDO::getDeleted, true).eq(ReceivableDO::getId, clearanceFeeReceivable.getId()));
                        }
                    }
                }
            }
        } else {
            if (type == 2) {
                return false;
            }
            if (Objects.nonNull(premiumFeeDto)) {
                ReceivableCreateReqVO reqVO = new ReceivableCreateReqVO();
                reqVO.setOrderId(orderDO.getOrderId());
                reqVO.setOrderNo(orderDO.getOrderNo());
                reqVO.setTitleZh(null);
                reqVO.setTitleEn(null);
                reqVO.setFeeType(6);
                reqVO.setFeeSource(1);
                reqVO.setPaymentUser(String.valueOf(orderDO.getDrawee() != 3 ? orderDO.getDrawee() : orderQueryService.customDrawee(orderDO, 6)));
                reqVO.setIsPayAdvance(0);
                reqVO.setCollectionType(4); // 到付
                reqVO.setUnitPrice(premiumFeeDto.getAmount().setScale(0, RoundingMode.HALF_UP));
                reqVO.setTotalAmount(premiumFeeDto.getAmount().setScale(0, RoundingMode.HALF_UP));
                reqVO.setTaxAmount(premiumFeeDto.getAmount().setScale(0, RoundingMode.HALF_UP));
                reqVO.setCurrencyId(Long.valueOf(premiumFeeDto.getCurrencyId()));
                receivableService.createReceivable(reqVO);
            }
            for (OrderItemDO orderItemDO : itemDOList) {

                if (Objects.isNull(orderItemDO.getWarehouseInInfoVO()) || orderItemDO.getWarehouseInInfoVO().getCartonsNum() == 0) {
                    continue;
                }

                if (Objects.nonNull(orderItemDO.getIsPayAdvance()) && orderItemDO.getIsPayAdvance() == 1) {
                    if (!Objects.equals(orderDO.getInWarehouseState(), OrderWarehouseInStatusEnum.warehouse_finished.getValue()) && orderDO.getShipmentState() == 0) {
                        continue;
                    }
                    isPayAdvanceException = true;
                } else {
//                    if (!Objects.equals(orderDO.getShipmentState(), OrderStatusMsgEnum.PRE_INSTALLED.getShipmentState())) {
                    if (Objects.isNull(orderDO.getShipmentState()) || orderDO.getShipmentState() == 0) {
                        continue;
                    }
                }
                this.createReceivable(orderDO, orderItemDO, 1, orderItemDO.getOneSeaFreight(), orderItemDO.getSeaFreight(), orderItemDO.getSeaFreightCurrency());

                if (orderItemDO.getCharging() == 0) {
                    this.createReceivable(orderDO, orderItemDO, 2, orderItemDO.getOneClearanceFreight(), orderItemDO.getClearanceFreight(), orderItemDO.getClearanceFreightCurrency());
                }

            }
        }
        return isPayAdvanceException;
    }


    /**
     * @param orderDO     订单信息
     * @param orderItemDO 订单商品项信息
     * @param feeType     费用类型 1 运费 2 清关费
     * @param unitPrice   单价
     * @param totalAmount 总额
     * @param currencyId  货币ID
     */
    private void createReceivable(OrderDO orderDO, OrderItemDO orderItemDO, Integer feeType, BigDecimal
            unitPrice, BigDecimal totalAmount, Integer currencyId) {
        if (Objects.nonNull(orderItemDO.getWarehouseInInfoVO()) && orderItemDO.getWarehouseInInfoVO().getCartonsNum() > 0) {
            if (Objects.isNull(orderItemDO.getIsPayAdvance())) {
                // TODO 这里来生成应收的都不可能为0, 在这里兼容可能发生的插件查询结果导致null值报空，默认给到付状态
                orderItemDO.setIsPayAdvance(0);
            }
            // 只有已入仓的订单项才可能生成应收单
            ReceivableCreateReqVO reqVO = new ReceivableCreateReqVO();
            reqVO.setOrderId(orderDO.getOrderId());
            reqVO.setOrderNo(orderDO.getOrderNo());
            reqVO.setOrderItemId(orderItemDO.getOrderItemId());
            reqVO.setTitleZh(orderItemDO.getProdTitleZh());
            reqVO.setTitleEn(orderItemDO.getProdTitleEn());
            reqVO.setFeeType(feeType);
            reqVO.setFeeSource(1);
            reqVO.setPaymentUser(String.valueOf(orderDO.getDrawee() != 3 ? orderDO.getDrawee() : orderQueryService.customDrawee(orderDO, feeType)));
            reqVO.setIsPayAdvance(Objects.isNull(orderItemDO.getIsPayAdvance()) ? 0 : orderItemDO.getIsPayAdvance());
            reqVO.setCollectionType(Objects.isNull(orderItemDO.getIsPayAdvance()) || orderItemDO.getIsPayAdvance() == 0 ? 4 : 1);

            reqVO.setNum(orderItemDO.getWarehouseInInfoVO().getCartonsNum());
            reqVO.setQuantity(orderItemDO.getChargeQuantity().compareTo(orderItemDO.getMinMeteringQuantity()) > 0 ? orderItemDO.getChargeQuantity().intValue() : orderItemDO.getMinMeteringQuantity().intValue());
            reqVO.setWeight(orderItemDO.getChargeWeight().compareTo(orderItemDO.getMinMeteringWeight()) > 0 ? orderItemDO.getChargeWeight() : orderItemDO.getMinMeteringWeight());
            reqVO.setVolume(orderItemDO.getChargeVolume().compareTo(orderItemDO.getMinMeteringVolume()) > 0 ? orderItemDO.getChargeVolume() : orderItemDO.getMinMeteringVolume());
            if (orderItemDO.getTransportId() == 1 || orderItemDO.getTransportId() == 2 || feeType == 1) {
                reqVO.setQuantity(orderItemDO.getChargeQuantity().compareTo(orderItemDO.getMinMeteringQuantity()) > 0 ? orderItemDO.getChargeQuantity().intValue() : orderItemDO.getMinMeteringQuantity().intValue());
                reqVO.setWeight(orderItemDO.getChargeWeight().compareTo(orderItemDO.getMinMeteringWeight()) > 0 ? orderItemDO.getChargeWeight() : orderItemDO.getMinMeteringWeight());
                reqVO.setVolume(orderItemDO.getChargeVolume().compareTo(orderItemDO.getMinMeteringVolume()) > 0 ? orderItemDO.getChargeVolume() : orderItemDO.getMinMeteringVolume());
            } else {
                // 空运清关费按实际入仓数据来计费
                Integer quantityAll = orderItemDO.getWarehouseInInfoVO().getQuantityAll();
                reqVO.setQuantity((Objects.isNull(quantityAll) ? BigDecimal.ZERO : new BigDecimal(quantityAll)).compareTo(orderItemDO.getMinMeteringQuantity()) > 0 ? quantityAll : orderItemDO.getMinMeteringQuantity().intValue());
                reqVO.setWeight(orderItemDO.getWarehouseInInfoVO().getWeight().compareTo(orderItemDO.getMinMeteringWeight()) > 0 ? orderItemDO.getWarehouseInInfoVO().getWeight() : orderItemDO.getMinMeteringWeight());
                reqVO.setVolume(orderItemDO.getWarehouseInInfoVO().getVolume().compareTo(orderItemDO.getMinMeteringVolume()) > 0 ? orderItemDO.getWarehouseInInfoVO().getVolume() : orderItemDO.getMinMeteringVolume());
            }
            reqVO.setAmountWorth(orderItemDO.getWorth());
            reqVO.setUnitPrice(unitPrice);
            reqVO.setTotalAmount(totalAmount.setScale(0, RoundingMode.HALF_UP));
            reqVO.setTaxAmount(totalAmount.setScale(0, RoundingMode.HALF_UP));
            reqVO.setCurrencyId(Long.valueOf(currencyId));
            receivableService.createReceivable(reqVO);
        }
    }


    /**
     * 添加订单动态日志
     *
     * @param status       最新变更订单状态
     * @param orderDO      订单信息
     * @param type         0 正常主状态变更 1 拆单后创建的新订单  2 合单后创建的新订单
     *                     3 特价-优惠申请通过 4 特价-管理折扣通过 5 特价-重货优惠通过 6 特价-泡货优惠通过
     *                     7、订单修改审批通过 8 入仓修改审批通过 9 佣金设置审批通过
     * @param businessTime 业务时间
     * @param now          业务系统同一创建时间
     */
    private void addOrderTimeLog(Integer status, OrderDO orderDO, Integer type, Date businessTime, Date now) {
        if (Objects.isNull(now)) {
            now = new Date();
        }
        this.addOrderTimeLogAndTime(status, orderDO, type, businessTime, now);
    }


    private void addOrderTimeLogAndTime(Integer status, OrderDO orderDO, Integer type, Date businessTime, Date now) {
        if (!Objects.equals(orderDO.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue()) && !Objects.equals(orderDO.getTransportId(), TransportTypeShortEnum.SEA_CONTAINER.getValue())) {
            if (type != 0) {
                return;
            }
            // 主订单状态发生改变时存入日志
            OrderTimeDO orderTimeDO = new OrderTimeDO();
            orderTimeDO.setStatus(status);
            orderTimeDO.setType(0);
            orderTimeDO.setOrderId(orderDO.getOrderId());
            orderTimeDO.setBusinessTime(Objects.isNull(businessTime) ? now : businessTime);
            orderTimeDO.setCreateTime(now);
            orderTimeDO.setCreator(String.valueOf(SecurityFrameworkUtils.getLoginUserId()));
            orderTimeDO.setUpdateTime(now);
            OrderStatusEnum orderStatusEnum = OrderStatusEnum.valueOf(status);
            // 封装状态备注
            BoxOrderDynamicEstTimeEvent event = new BoxOrderDynamicEstTimeEvent(orderDO.getContainerNumber(), 0, null);
            String estTime = "";
            switch (orderStatusEnum) {
                case INSTALLED_CABINET:
                    // 查询出货订舱表 ecw_box_book_sea 获取预计开船时间
                    event.setType(10);
                    applicationContext.publishEvent(event);
                    estTime = Objects.nonNull(event.getEstTime()) ? DateUtil.formatDateTime(event.getEstTime()) : "";
                    break;
                case IN_SHIPPING:
                    // 查询出货起运表 ecw_box_shipping 获取预计到港时间
                    event.setType(11);
                    applicationContext.publishEvent(event);
                    estTime = Objects.nonNull(event.getEstTime()) ? DateUtil.formatDateTime(event.getEstTime()) : "";
                    break;
//            case ARRIVED:
//                // 查询出货清关表 ecw_box_clearance 获取预计清关时间
//                event.setType(12);
//                applicationContext.publishEvent(event);
//                break;
                case PART_PICKED_UP:
                    // 部分提货
                    estTime = Objects.nonNull(businessTime) ? DateUtil.formatDateTime(businessTime) : "";
                    break;
                case PICKED_UP:
                    // 全部提货
                    estTime = Objects.nonNull(businessTime) ? DateUtil.formatDateTime(businessTime) : "";
                    break;
                default:
                    break;
            }
            if (StringUtils.isNotBlank(estTime) && (StringUtils.isNotBlank(orderStatusEnum.getRemarksZh()) || StringUtils.isNotBlank(orderStatusEnum.getRemarksEn()))) {
                orderTimeDO.setRemarksZh(orderStatusEnum.getRemarksZh() + estTime);
                orderTimeDO.setRemarksEn(orderStatusEnum.getRemarksEn() + estTime);
            }
//            switch (type) {
//                case 1:
//                    orderTimeDO.setType(1);
//                    orderTimeDO.setTitleZh("拆单成功" );
//                    orderTimeDO.setTitleEn("The order is successfully split");
//                    break;
//                case 2:
//                    orderTimeDO.setType(2);
//                    orderTimeDO.setTitleZh("合单成功,已入仓");
//                    orderTimeDO.setTitleEn("The order has been successfully closed and has been put into the warehouse" );
//                    break;
//                case 3:
//                    orderTimeDO.setType(3);
//                    orderTimeDO.setTitleZh("特价-优惠申请通过");
//                    orderTimeDO.setTitleEn("Special price - preferential application passed");
//                    break;
//                case 4:
//                    orderTimeDO.setType(4);
//                    orderTimeDO.setTitleZh("特价-管理折扣通过");
//                    orderTimeDO.setTitleEn("Special Price - Manage Discount Pass");
//                    break;
//                case 5:
//                    orderTimeDO.setType(5);
//                    orderTimeDO.setTitleZh("特价-重货优惠通过");
//                    orderTimeDO.setTitleEn("Special Price - Heavy Goods Discount Pass");
//                    break;
//                case 6:
//                    orderTimeDO.setType(6);
//                    orderTimeDO.setTitleZh("特价-泡货优惠通过");
//                    orderTimeDO.setTitleEn("Special Price - Bubble Discount Pass");
//                    break;
//                case 7:
//                    orderTimeDO.setType(7);
//                    orderTimeDO.setTitleZh("订单修改审批通过");
//                    orderTimeDO.setTitleEn("Order modification approved");
//                    break;
//                case 8:
//                    orderTimeDO.setType(8);
//                    orderTimeDO.setTitleZh("入仓修改审批通过");
//                    orderTimeDO.setTitleEn("Warehouse entry modification approved");
//                    break;
//                case 9:
//                    orderTimeDO.setType(9);
//                    orderTimeDO.setTitleZh("佣金设置审批通过");
//                    orderTimeDO.setTitleEn("Commission setting approved");
//                    break;
//                case 10:
//                    orderTimeDO.setType(10);
//                    orderTimeDO.setTitleZh("撤销拆单成功");
//                    orderTimeDO.setTitleEn("Successfully cancelled the split order");
//                    break;
//                case 11:
//                    orderTimeDO.setType(11);
//                    orderTimeDO.setTitleZh("特价-批量优惠申请通过");
//                    orderTimeDO.setTitleEn("Special price - Batch preferential application passed");
//                    break;
//                case 12:
//                    orderTimeDO.setType(12);
//                    orderTimeDO.setTitleZh("特价-批量管理折扣通过");
//                    orderTimeDO.setTitleEn("Special Price - Batch Manage Discount Pass");
//                    break;
//                default:
//                    orderTimeDO.setType(0);
//                    orderTimeDO.setTitleZh((Objects.nonNull(orderDO.getPrefixStatusZh()) ? orderDO.getPrefixStatusZh() : "") + orderStatusEnum.getNameZh());
//                    orderTimeDO.setTitleEn((Objects.nonNull(orderDO.getPrefixStatusEn()) ? orderDO.getPrefixStatusEn() : "") + orderStatusEnum.getNameEn());
//                    break;
//            }
            orderTimeDO.setTitleZh((Objects.nonNull(orderDO.getPrefixStatusZh()) ? orderDO.getPrefixStatusZh() : "") + orderStatusEnum.getNameZh());
            orderTimeDO.setTitleEn((Objects.nonNull(orderDO.getPrefixStatusEn()) ? orderDO.getPrefixStatusEn() : "") + orderStatusEnum.getNameEn());
            orderTimeMapper.insert(orderTimeDO);
        }
    }

    @Override
    public void updateOrderType(Long orderId, Integer orderType) {
        this.update(new LambdaUpdateWrapper<OrderDO>().set(OrderDO::getOrderType, orderType).eq(OrderDO::getOrderId, orderId));
        // 更新订单操作日志
        ApplyInfoVO infoVO = new ApplyInfoVO();
        infoVO.setName("订单类型");
        infoVO.setNewValue(orderType == 2 ? "重货" : (orderType == 3 ? "泡货" : "普货"));
        orderBusinessService.addOrderOperateLog(orderId, "订单类型更新", JSONObject.toJSONString(Collections.singletonList(infoVO)));
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void specialApplyOrder(OrderSpecialApplyVO specialApplyVO) {
        String creator = String.valueOf(SecurityFrameworkUtils.getLoginUserId());
        OrderDO orderDO = orderMapper.selectById(specialApplyVO.getOrderId());
        if (Objects.isNull(orderDO)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        OrderApprovalTypeEnum typeEnum = OrderApprovalTypeEnum.valueOf(specialApplyVO.getApplyType());
        if (Objects.isNull(typeEnum)) {
            throw exception(ORDER_APPROVAL_IS_NOT_EXISTS);
        }
        OrderApprovalTypeCheckEvent approvalTypeCheckEvent = new OrderApprovalTypeCheckEvent(specialApplyVO.getOrderId(), Objects.nonNull(specialApplyVO.getOrderItemId()) ?
                Collections.singletonList(specialApplyVO.getOrderItemId()) : null, typeEnum.getValue(), null, false);
        applicationContext.publishEvent(approvalTypeCheckEvent);
        if (approvalTypeCheckEvent.getResult()) {
            throw exception(ORDER_IS_APPROVAL_IN_PROCESS);
        }
        int count = orderApprovalMapper.processingItemApproval(specialApplyVO.getOrderItemId(), specialApplyVO.getOrderId(), Arrays.asList(1, 2, 3));
        if (count > 0) {
            throw exception(ITEM_SPECIAL_APPLY_NO_MULTIPLE_PROGRESS);
        }
        Long orderItemId = null;
        List<OrderItemDO> orderItemDOList = new ArrayList<>();
        if (specialApplyVO.getApplyType() != 4 && specialApplyVO.getApplyType() != 5 && specialApplyVO.getApplyType() != 29) {

            OrderItemDO orderItemDO = orderItemMapper.selectById(specialApplyVO.getOrderItemId());
            if (Objects.isNull(orderItemDO)) {
                throw exception(ORDER_ITEM_PROD_NOT_EXISTS);
            }
            // 校验是否有已核销的应收单，如果有，则不能再次入仓修改
            receivableService.verificationReceivableIsWriteOff(null, orderItemDO.getOrderItemId());
            if (specialApplyVO.getApplyType() == 1 && specialApplyVO.getApplyType() == 2) {
                if (Objects.isNull(specialApplyVO.getFreight()) || specialApplyVO.getFreight().compareTo(orderItemDO.getHiddenCommission().add(orderItemDO.getPlainCommission())) <= 0) {
                    throw exception(FINAL_SALE_FREIGHT_AMOUNT_MUST_GT_ZERO);
                }
                if (specialApplyVO.getFreight().compareTo(specialApplyVO.getOrgFreight()) == 0) {
                    throw exception(SPECIAL_APPLY_DISCOUNT_FREIGHT_NEW_AMOUNT_NOT_EQ_ORG_AMOUNT);
                }
                if (Objects.isNull(specialApplyVO.getClearanceFreight()) || specialApplyVO.getClearanceFreight().compareTo(BigDecimal.ZERO) <= 0) {
                    throw exception(FINAL_SALE_CLEARANCE_AMOUNT_MUST_GT_ZERO);
                }
                if (specialApplyVO.getClearanceFreight().compareTo(specialApplyVO.getOrgClearanceFreight()) == 0) {
                    throw exception(SPECIAL_APPLY_DISCOUNT_CLEARANCE_NEW_AMOUNT_NOT_EQ_ORG_AMOUNT);
                }
            }


            if (specialApplyVO.getApplyType() == 3) {
                if (Objects.isNull(specialApplyVO.getCommissionType())) {
                    throw exception(COMMISSION_TYPE_NOT_NULL);
                }
                specialApplyVO.setOrgFreight(orderItemDO.getOneSeaFreight());
                specialApplyVO.setOrgCommissionType(orderItemDO.getCommissionType());
                specialApplyVO.setOrgLightCommissionAmount(orderItemDO.getPlainCommission());
                specialApplyVO.setOrgShadeCommissionAmount(orderItemDO.getHiddenCommission());
                // 佣金申请成功 需要重新计算新的运费清关费
                // 需要修改销售单价金额 ，先获取原始不包含佣金的销售单价金额
                BigDecimal saleAmount = orderItemDO.getOneSeaFreight().subtract(orderItemDO.getPlainCommission());
                if (specialApplyVO.getCommissionType() == 0) {
                    specialApplyVO.setLightCommissionAmount(BigDecimal.ZERO);
                    specialApplyVO.setShadeCommissionAmount(BigDecimal.ZERO);
                }
                if (specialApplyVO.getCommissionType() == 1) {
                    specialApplyVO.setShadeCommissionAmount(BigDecimal.ZERO);
                } else if (specialApplyVO.getCommissionType() == 2 || specialApplyVO.getCommissionType() == 3) {
                    BigDecimal costAmount = saleAmount.subtract(specialApplyVO.getLightCommissionAmount());
                    if (costAmount.compareTo(BigDecimal.ZERO) < 0) {
                        throw exception(FINAL_SALE_FREIGHT_AMOUNT_MUST_GT_ZERO);
                    }
                }
                saleAmount = saleAmount.add(specialApplyVO.getLightCommissionAmount());
                specialApplyVO.setFreight(saleAmount);
            }
            orderItemId = orderItemDO.getOrderItemId();
            orderItemDOList.add(orderItemDO);
        } else {
            // 校验是否有已核销的应收单，如果有，则不能再次入仓修改
            receivableService.verificationReceivableIsWriteOff(orderDO.getOrderId(), null);
            // 拆单子订单，没有空运订单参与，以母订单数据为准，申请优惠时，提示“非独立子订单，不可进行优惠申请”
            if (!orderDO.getSplitSeparateOrder() && Objects.nonNull(orderDO.getParentOrderId()) && orderDO.getParentOrderId() > 0L) {
                throw exception(SPLIT_NOT_SEPARATE_ORDER_NO_CAN_HEAVY_PICKLED_GOODS_DISCOUNT_APPLY);
            }
            if (specialApplyVO.getApplyType() == 4 && Objects.isNull(specialApplyVO.getWVolume())) {
                throw exception(HEAVY_CARGO_DISCOUNT_SET_VALUE_NOT_NULL);
            }
            if (specialApplyVO.getApplyType() == 5 && Objects.isNull(specialApplyVO.getVWeight())) {
                throw exception(BUBBLE_CARGO_DISCOUNT_SET_VALUE_NOT_NULL);
            }
            if (specialApplyVO.getApplyType() == 29 && Objects.isNull(specialApplyVO.getVWeight())) {
                throw exception(BUBBLE_CARGO_DISCOUNT_SET_VALUE_NOT_NULL);
            }
            orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, specialApplyVO.getOrderId()));
        }

        OrderApprovalDO orderApprovalDO = orderApprovalMapper.newItemInfo(orderItemId, specialApplyVO.getOrderId(), specialApplyVO.getApplyType());
        if (Objects.nonNull(orderApprovalDO) && orderApprovalDO.getStatus() == 1) {
            throw exception(YOUR_APPLY_PENDING);
        }
        orderApprovalDO = new OrderApprovalDO();
        orderApprovalDO.setOrderId(specialApplyVO.getOrderId());
        orderApprovalDO.setType(specialApplyVO.getApplyType());
        orderApprovalDO.setFollowUpSalesmanId(String.valueOf(orderDO.getSalesmanId()));//跟进业务员为订单的跟进业务员
        specialApplyVO.setApplyStatus(1);
        orderApprovalDO.setDetails(JSONObject.toJSONString(specialApplyVO));
        orderApprovalDO.setCreator(creator);
        orderApprovalDO.setUpdater(creator);
        orderApprovalDO.setCreateTime(new Date());
        orderApprovalDO.setUpdateTime(new Date());
        orderApprovalMapper.insert(orderApprovalDO);
        // 创建流程实例
        String key;
        List<ApplyInfoVO> applyInfoVOList = new ArrayList<>();
        Map<Integer, CurrencyRespDTO> currencyRespDTOMap = currencyApi.getAllCurrency();
        Map<Integer, UnitRespDto> unitRespDtoMap = unitApi.getAllUnit();
        ApplyInfoVO applyInfoVO = new ApplyInfoVO();
//        BoxCheckOrderSchedulingEvent event = new BoxCheckOrderSchedulingEvent(orderDO.getOrderId());
        switch (specialApplyVO.getApplyType()) {
            case 1:
                applyInfoVO.setName(specialApplyVO.getProdTitleZh() + (specialApplyVO.getCharging() == 1 ? "全包价优惠" : "运费优惠"));
                applyInfoVO.setOrgValue(specialApplyVO.getOrgFreight().toString() + currencyRespDTOMap.get(specialApplyVO.getFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(specialApplyVO.getFreightVolume().intValue()).getTitleZh());
                applyInfoVO.setNewValue(specialApplyVO.getFreight().toString() + currencyRespDTOMap.get(specialApplyVO.getFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(specialApplyVO.getFreightVolume().intValue()).getTitleZh());
                applyInfoVOList.add(applyInfoVO);
                if (specialApplyVO.getCharging() == 0) {
                    applyInfoVO = new ApplyInfoVO();
                    applyInfoVO.setName(specialApplyVO.getProdTitleZh() + "清关费优惠");
                    applyInfoVO.setOrgValue(specialApplyVO.getOrgClearanceFreight().toString() + currencyRespDTOMap.get(specialApplyVO.getClearanceFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(specialApplyVO.getClearanceFreightVolume().intValue()).getTitleZh());
                    applyInfoVO.setNewValue(specialApplyVO.getClearanceFreight().toString() + currencyRespDTOMap.get(specialApplyVO.getClearanceFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(specialApplyVO.getClearanceFreightVolume().intValue()).getTitleZh());
                    applyInfoVOList.add(applyInfoVO);
                }
                // TODO 只能装柜前、到港后申请
                key = WorkFlowEmus.ORDER_SPECIAL_APPLY.getKey();
                break;
            case 2:
                applyInfoVO.setName(specialApplyVO.getProdTitleZh() + (specialApplyVO.getCharging() == 1 ? "全包价管理折扣" : "运费管理折扣"));
                applyInfoVO.setOrgValue(specialApplyVO.getOrgFreight().toString() + currencyRespDTOMap.get(specialApplyVO.getFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(specialApplyVO.getFreightVolume().intValue()).getTitleZh());
                applyInfoVO.setNewValue(specialApplyVO.getFreight().toString() + currencyRespDTOMap.get(specialApplyVO.getFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(specialApplyVO.getFreightVolume().intValue()).getTitleZh());
                applyInfoVOList.add(applyInfoVO);
                if (specialApplyVO.getCharging() == 0) {
                    applyInfoVO = new ApplyInfoVO();
                    applyInfoVO.setName(specialApplyVO.getProdTitleZh() + "清关费管理折扣");
                    applyInfoVO.setOrgValue(specialApplyVO.getOrgClearanceFreight().toString() + currencyRespDTOMap.get(specialApplyVO.getClearanceFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(specialApplyVO.getClearanceFreightVolume().intValue()).getTitleZh());
                    applyInfoVO.setNewValue(specialApplyVO.getClearanceFreight().toString() + currencyRespDTOMap.get(specialApplyVO.getClearanceFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(specialApplyVO.getClearanceFreightVolume().intValue()).getTitleZh());
                    applyInfoVOList.add(applyInfoVO);
                }
                // TODO 订单核销前都可以申请
                key = WorkFlowEmus.ORDER_MANAGE_DISCOUNTS.getKey();
                break;
            case 3:
                if (specialApplyVO.getCommissionType() == 1 || specialApplyVO.getCommissionType() == 3) {
                    applyInfoVO.setName(specialApplyVO.getProdTitleZh() + "明佣金额");
                    applyInfoVO.setOrgValue(specialApplyVO.getOrgLightCommissionAmount().toString() + currencyRespDTOMap.get(specialApplyVO.getFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(specialApplyVO.getFreightVolume().intValue()).getTitleZh());
                    applyInfoVO.setNewValue(specialApplyVO.getLightCommissionAmount().toString() + currencyRespDTOMap.get(specialApplyVO.getFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(specialApplyVO.getFreightVolume().intValue()).getTitleZh());
                    applyInfoVOList.add(applyInfoVO);
                }
                if (specialApplyVO.getCommissionType() == 2 || specialApplyVO.getCommissionType() == 3) {
                    applyInfoVO = new ApplyInfoVO();
                    applyInfoVO.setName(specialApplyVO.getProdTitleZh() + "暗佣金额");
                    applyInfoVO.setOrgValue(specialApplyVO.getOrgShadeCommissionAmount().toString() + currencyRespDTOMap.get(specialApplyVO.getFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(specialApplyVO.getFreightVolume().intValue()).getTitleZh());
                    applyInfoVO.setNewValue(specialApplyVO.getShadeCommissionAmount().toString() + currencyRespDTOMap.get(specialApplyVO.getFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(specialApplyVO.getFreightVolume().intValue()).getTitleZh());
                    applyInfoVOList.add(applyInfoVO);
                }
                key = WorkFlowEmus.ORDER_COMMISSION_CONFIG.getKey();
                break;
            case 4:
                applyInfoVO.setName("重货优惠");
                applyInfoVO.setOrgValue(specialApplyVO.getOrgWVolume().toString());
                applyInfoVO.setNewValue(specialApplyVO.getWVolume().toString());
                applyInfoVOList.add(applyInfoVO);
//                applicationContext.publishEvent(event);
                key = WorkFlowEmus.ORDER_HEAVY_GOODS.getKey();
                break;
            case 5:
                applyInfoVO.setName("泡货优惠");
                applyInfoVO.setOrgValue(specialApplyVO.getOrgVWeight().toString());
                applyInfoVO.setNewValue(specialApplyVO.getVWeight().toString());
                applyInfoVOList.add(applyInfoVO);
//                applicationContext.publishEvent(event);
                key = WorkFlowEmus.ORDER_LIGHT_GOODS.getKey();
                break;
            case 29:
                applyInfoVO.setName("泡重优惠");
                applyInfoVO.setOrgValue(specialApplyVO.getOrgVWeight().toString());
                applyInfoVO.setNewValue(specialApplyVO.getVWeight().toString());
                applyInfoVOList.add(applyInfoVO);
//                applicationContext.publishEvent(event);
                key = WorkFlowEmus.SHIPMENT_BULKY_CARGO.getKey();
                break;
            default:
                throw exception(ORDER_APPLY_TYPE_NOT_EXISTS);
        }
        String formId = bpmCreateServiceFactory.createBmp(Long.valueOf(creator), orderApprovalDO.getOrderApprovalId(), key, orderDO.getOrderNo(), StringUtils.isNotBlank(specialApplyVO.getCcIds()) ? specialApplyVO.getCcIds().split(StrUtil.COMMA) : null);
        orderApprovalDO.setFormId(formId);
        orderApprovalMapper.updateById(orderApprovalDO);

        orderItemDOList = orderItemDOList.stream().peek(orderItemDO -> orderItemDO.setItemStatus(1)).collect(Collectors.toList());
        orderItemMapper.updateBatch(orderItemDOList);


        this.updateStatus(orderDO.getOrderId(), null, null, null, null,
                null, specialApplyVO.getApplyType(), this.getAuditResult(1, specialApplyVO.getApplyType()), null, null, JSONObject.toJSONString(applyInfoVOList));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void specialBatchApplyOrder(OrderSpecialBatchApplyVO specialBatchApplyVO) {
        String creator = String.valueOf(SecurityFrameworkUtils.getLoginUserId());
        OrderDO orderDO = orderMapper.selectById(specialBatchApplyVO.getOrderId());
        if (Objects.isNull(orderDO)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        OrderApprovalTypeEnum typeEnum = OrderApprovalTypeEnum.valueOf(specialBatchApplyVO.getApplyType());
        if (Objects.isNull(typeEnum)) {
            throw exception(ORDER_APPROVAL_IS_NOT_EXISTS);
        }
        List<Long> orderItemIdList = specialBatchApplyVO.getBatchApplyOrderItemDetailVOList().stream().map(OrderSpecialBatchApplyOrderItemDetailVO::getOrderItemId).filter(Objects::nonNull).collect(Collectors.toList());
        OrderApprovalTypeCheckEvent approvalTypeCheckEvent = new OrderApprovalTypeCheckEvent(specialBatchApplyVO.getOrderId(), orderItemIdList, typeEnum.getValue(), null, false);
        applicationContext.publishEvent(approvalTypeCheckEvent);
        if (approvalTypeCheckEvent.getResult()) {
            throw exception(ORDER_IS_APPROVAL_IN_PROCESS);
        }
        int count = orderApprovalMapper.processingItemApproval(null, specialBatchApplyVO.getOrderId(),
                Arrays.asList(OrderApprovalTypeEnum.DISCOUNT_APPLY_BATCH.getValue(), OrderApprovalTypeEnum.ADMIN_DISCOUNT_BATCH.getValue()));
        if (count > 0) {
            throw exception(ITEM_SPECIAL_APPLY_NO_MULTIPLE_PROGRESS);
        }
        List<OrderItemDO> orderItemDOList = new ArrayList<>();

        List<OrderSpecialBatchApplyOrderItemDetailVO> batchApplyOrderItemDetailVOList = specialBatchApplyVO.getBatchApplyOrderItemDetailVOList();

        if (CollectionUtil.isNotEmpty(batchApplyOrderItemDetailVOList)) {

            for (OrderSpecialBatchApplyOrderItemDetailVO batchApplyOrderItemDetailVO : batchApplyOrderItemDetailVOList) {

                OrderItemDO orderItemDO = orderItemMapper.selectById(batchApplyOrderItemDetailVO.getOrderItemId());
                if (Objects.isNull(orderItemDO)) {
                    throw exception(ORDER_ITEM_PROD_NOT_EXISTS);
                }
                // 校验是否有已核销的应收单，如果有，则不能再次入仓修改
                receivableService.verificationReceivableIsWriteOff(null, orderItemDO.getOrderItemId());
                if (specialBatchApplyVO.getApplyType() == 1 && specialBatchApplyVO.getApplyType() == 2) {
                    if (Objects.isNull(batchApplyOrderItemDetailVO.getFreight()) || batchApplyOrderItemDetailVO.getFreight().compareTo(orderItemDO.getHiddenCommission().add(orderItemDO.getPlainCommission())) <= 0) {
                        throw exception(FINAL_SALE_FREIGHT_AMOUNT_MUST_GT_ZERO);
                    }
                    if (batchApplyOrderItemDetailVO.getFreight().compareTo(batchApplyOrderItemDetailVO.getOrgFreight()) == 0) {
                        throw exception(SPECIAL_APPLY_DISCOUNT_FREIGHT_NEW_AMOUNT_NOT_EQ_ORG_AMOUNT);
                    }
                    if (Objects.isNull(batchApplyOrderItemDetailVO.getClearanceFreight()) || batchApplyOrderItemDetailVO.getClearanceFreight().compareTo(BigDecimal.ZERO) <= 0) {
                        throw exception(FINAL_SALE_CLEARANCE_AMOUNT_MUST_GT_ZERO);
                    }
                    if (batchApplyOrderItemDetailVO.getClearanceFreight().compareTo(batchApplyOrderItemDetailVO.getOrgClearanceFreight()) == 0) {
                        throw exception(SPECIAL_APPLY_DISCOUNT_CLEARANCE_NEW_AMOUNT_NOT_EQ_ORG_AMOUNT);
                    }
                }
                orderItemDOList.add(orderItemDO);
            }
        }


        OrderApprovalDO orderApprovalDO = orderApprovalMapper.newItemInfo(null, specialBatchApplyVO.getOrderId(), specialBatchApplyVO.getApplyType());
        if (Objects.nonNull(orderApprovalDO) && orderApprovalDO.getStatus() == 1) {
            throw exception(YOUR_APPLY_PENDING);
        }
        orderApprovalDO = new OrderApprovalDO();
        orderApprovalDO.setOrderId(specialBatchApplyVO.getOrderId());
        orderApprovalDO.setType(specialBatchApplyVO.getApplyType());
        orderApprovalDO.setFollowUpSalesmanId(String.valueOf(orderDO.getSalesmanId()));//跟进业务员为订单的跟进业务员
        specialBatchApplyVO.setApplyStatus(1);
        orderApprovalDO.setDetails(JSONObject.toJSONString(specialBatchApplyVO));
        orderApprovalDO.setCreator(creator);
        orderApprovalDO.setUpdater(creator);
        orderApprovalDO.setCreateTime(new Date());
        orderApprovalDO.setUpdateTime(new Date());
        orderApprovalMapper.insert(orderApprovalDO);
        // 创建流程实例
        String key = null;
        List<ApplyInfoVO> applyInfoVOList = new ArrayList<>();
        Map<Integer, CurrencyRespDTO> currencyRespDTOMap = currencyApi.getAllCurrency();
        Map<Integer, UnitRespDto> unitRespDtoMap = unitApi.getAllUnit();

        // BoxCheckOrderSchedulingEvent event = new BoxCheckOrderSchedulingEvent(orderDO.getOrderId());

        if (CollectionUtil.isNotEmpty(specialBatchApplyVO.getBatchApplyOrderItemDetailVOList())) {

            for (OrderSpecialBatchApplyOrderItemDetailVO vo : specialBatchApplyVO.getBatchApplyOrderItemDetailVOList()) {
                ApplyInfoVO applyInfoVO = new ApplyInfoVO();

                switch (specialBatchApplyVO.getApplyType()) {
                    case 31:
                        applyInfoVO.setName(vo.getProdTitleZh() + (vo.getCharging() == 1 ? "全包价优惠" : "运费优惠"));
                        applyInfoVO.setOrgValue(vo.getOrgFreight().toString() + currencyRespDTOMap.get(vo.getFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(vo.getFreightVolume().intValue()).getTitleZh());
                        applyInfoVO.setNewValue(vo.getFreight().toString() + currencyRespDTOMap.get(vo.getFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(vo.getFreightVolume().intValue()).getTitleZh());
                        applyInfoVOList.add(applyInfoVO);
                        if (vo.getCharging() == 0) {
                            applyInfoVO = new ApplyInfoVO();
                            applyInfoVO.setName(vo.getProdTitleZh() + "清关费优惠");
                            applyInfoVO.setOrgValue(vo.getOrgClearanceFreight().toString() + currencyRespDTOMap.get(vo.getClearanceFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(vo.getClearanceFreightVolume().intValue()).getTitleZh());
                            applyInfoVO.setNewValue(vo.getClearanceFreight().toString() + currencyRespDTOMap.get(vo.getClearanceFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(vo.getClearanceFreightVolume().intValue()).getTitleZh());
                            applyInfoVOList.add(applyInfoVO);
                        }
                        // TODO 只能装柜前、到港后申请
                        key = WorkFlowEmus.ORDER_SPECIAL_APPLY_BATCH.getKey();
                        break;
                    case 32:
                        applyInfoVO.setName(vo.getProdTitleZh() + (vo.getCharging() == 1 ? "全包价管理折扣" : "运费管理折扣"));
                        applyInfoVO.setOrgValue(vo.getOrgFreight().toString() + currencyRespDTOMap.get(vo.getFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(vo.getFreightVolume().intValue()).getTitleZh());
                        applyInfoVO.setNewValue(vo.getFreight().toString() + currencyRespDTOMap.get(vo.getFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(vo.getFreightVolume().intValue()).getTitleZh());
                        applyInfoVOList.add(applyInfoVO);
                        if (vo.getCharging() == 0) {
                            applyInfoVO = new ApplyInfoVO();
                            applyInfoVO.setName(vo.getProdTitleZh() + "清关费管理折扣");
                            applyInfoVO.setOrgValue(vo.getOrgClearanceFreight().toString() + currencyRespDTOMap.get(vo.getClearanceFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(vo.getClearanceFreightVolume().intValue()).getTitleZh());
                            applyInfoVO.setNewValue(vo.getClearanceFreight().toString() + currencyRespDTOMap.get(vo.getClearanceFreightCurrency().intValue()).getTitleZh() + "/" + unitRespDtoMap.get(vo.getClearanceFreightVolume().intValue()).getTitleZh());
                            applyInfoVOList.add(applyInfoVO);
                        }
                        // TODO 订单核销前都可以申请
                        key = WorkFlowEmus.ORDER_MANAGE_DISCOUNTS_BATCH.getKey();
                        break;
                    default:
                        throw exception(ORDER_APPLY_TYPE_NOT_EXISTS);
                }

            }

        }

        String formId = bpmCreateServiceFactory.createBmp(Long.valueOf(creator), orderApprovalDO.getOrderApprovalId(), key, orderDO.getOrderNo(),
                StringUtils.isNotBlank(specialBatchApplyVO.getCcIds()) ? specialBatchApplyVO.getCcIds().split(StrUtil.COMMA) : null);
        orderApprovalDO.setFormId(formId);
        orderApprovalMapper.updateById(orderApprovalDO);

        orderItemDOList = orderItemDOList.stream().peek(orderItemDO -> orderItemDO.setItemStatus(1)).collect(Collectors.toList());
        orderItemMapper.updateBatch(orderItemDOList);


        this.updateStatus(orderDO.getOrderId(), null, null, null, null,
                null, specialBatchApplyVO.getApplyType(), this.getAuditResult(1, specialBatchApplyVO.getApplyType()), null, null, JSONObject.toJSONString(applyInfoVOList));

    }

    @Override
    public void cancelOrderSpecialApproval(Long approveId, String reason) {
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        Integer userType = loginUser != null ? loginUser.getUserType() : null;
        Long userId = loginUser != null ? loginUser.getId() : null;
        if (Objects.equals(userType, UserTypeEnum.MEMBER.getValue())) {
            DictDataRespDTO dto = dictDataApi.parseDictDataFromCache(CUSTOMER_USER_TO_ADMIN, CUSTOMER_USER_APPROVAL_ID);
            userId = Long.valueOf(dto.getValue());
        }
        OrderApprovalDO approvalDO = orderApprovalMapper.selectById(approveId);
        if (approvalDO.getDeleted() || (approvalDO.getType() != 1 && approvalDO.getType() != 2 && approvalDO.getType() != 3 && approvalDO.getType() != 4 && approvalDO.getType() != 5 && approvalDO.getStatus() != 1)) {
            throw exception(ORDER_APPROVAL_STATUS_NOT_CORRECT);
        }
        if (Objects.isNull(approvalDO.getFormId())) {
            throw exception(ORDER_APPROVAL_FORM_ID_NOT_EXISTS);
        }
        bpmCreateServiceFactory.cancelBmpById(userId, approvalDO.getFormId(), reason);
    }

    private String getApprovalTypeMsg(Integer type) {
        DictDataRespDTO dto = DictFrameworkUtils.getDictDataFromCache("order_approval_type", String.valueOf(type));
        return Objects.isNull(dto) ? "" : dto.getLabel();
    }

    /**
     * @param approveId 表单业务ID
     * @param result    1 处理中  2 通过 3 不通过 4 已取消
     */
    @Override
    public void approvalOrder(String approveId, Integer result) {
        OrderApprovalDO orderApprovalDO =
                orderApprovalMapper.selectById(approveId);
        if (Objects.isNull(orderApprovalDO)) {
            throw exception(ORDER_APPROVAL_INFO_NOT_FIND);
        }
        orderApprovalDO.setStatus(result);
        if (result == 1) {
            // 进行中的审批直接返回
            return;
        }
        OrderDO orderDO = orderMapper.selectById(orderApprovalDO.getOrderId());
        if (Objects.isNull(orderDO)) {
            return;
        }
        // 查询最后审核的详细信息
        TaskResp taskResp = bpmCreateServiceFactory.getLastTaskByProcessInstanceId(orderApprovalDO.getFormId());
        if (Objects.equals(orderApprovalDO.getType(), ORDER_UPDATE.getValue())) {
            // 订单修改
            OrderBackVO orderBackVO = JSONObject.parseObject(orderApprovalDO.getDetails(), OrderBackVO.class);
            orderBackVO.setApplyStatus(result);
            orderBackVO.setApplyType(ORDER_UPDATE.getValue());
            orderBackVO.setApplyResult(taskResp.getComment());
            orderApprovalDO.setDetails(JSONObject.toJSONString(orderBackVO));
            orderApprovalDO.setFinishBy(String.valueOf(taskResp.getAssigneeUser().getId()));
            orderApprovalDO.setFinishTime(new Date());
            orderApprovalDO.setProcessingResults(taskResp.getComment());
            // 更新审批结果
            orderApprovalMapper.updateById(orderApprovalDO);
            if (result == 3 || result == 4) {
                this.updateStatus(orderDO.getOrderId(), null, null, null, null, null, 0, this.getAuditResult(result, ORDER_UPDATE.getValue()), null, null, JSONObject.toJSONString(orderBackVO.getApplyInfoList()));
                return;
            }
            // 审批通过
            // 订单修改，更新订单信息
            this.approvalUpdateOrder(orderBackVO, taskResp.getAssigneeUser().getId());

        }
        //批量特价申请
        else if (Objects.equals(orderApprovalDO.getType(),
                OrderApprovalTypeEnum.DISCOUNT_APPLY_BATCH.getValue())
                || Objects.equals(orderApprovalDO.getType(),
                OrderApprovalTypeEnum.ADMIN_DISCOUNT_BATCH.getValue())) {

            OrderSpecialBatchApplyVO specialBatchApplyVO = JSONObject.parseObject(orderApprovalDO.getDetails(), OrderSpecialBatchApplyVO.class);
            specialBatchApplyVO.setApplyStatus(result);
            specialBatchApplyVO.setApplyResult(taskResp.getComment());
            // 查询最后审核的详细信息
            orderApprovalDO.setDetails(JSONObject.toJSONString(specialBatchApplyVO));
            orderApprovalDO.setFinishBy(String.valueOf(taskResp.getAssigneeUser().getId()));
            orderApprovalDO.setFinishTime(new Date());
            orderApprovalDO.setProcessingResults(taskResp.getComment());
            // 更新审批结果
            orderApprovalMapper.updateById(orderApprovalDO);

            // 开始根据审批结果更新订单及订单项信息
            List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderDO.getOrderId()));
            if (CollectionUtil.isEmpty(orderItemDOList)) {
                return;
            }

            List<OrderSpecialBatchApplyOrderItemDetailVO> batchApplyOrderItemDetailVOList = specialBatchApplyVO.getBatchApplyOrderItemDetailVOList();
            if (CollectionUtil.isEmpty(batchApplyOrderItemDetailVOList)) {
                return;
            }

            //
            boolean orderStatusUpdated = false;
            for (OrderSpecialBatchApplyOrderItemDetailVO batchApplyOrderItemDetailVO : batchApplyOrderItemDetailVOList) {

                // 查询特价申请的审批类型是否有在处理中的
                OrderApprovalDO processingItemBatchApproval = orderApprovalService.getProcessingItemBatchApproval(specialBatchApplyVO.getOrderId(), batchApplyOrderItemDetailVO.getOrderItemId());
                // 没有批量特价正在处理中
                boolean notExistProcessingItemBatchApproval = processingItemBatchApproval == null;
                if (notExistProcessingItemBatchApproval) {
                    // 有正在处理中的申请
                    orderItemDOList = orderItemDOList.stream().peek(oi -> {
                        if (Objects.equals(oi.getOrderItemId(), batchApplyOrderItemDetailVO.getOrderItemId())) {
                            oi.setItemStatus(0);
                        }
                    }).collect(Collectors.toList());
                }

                if (result == 3 || result == 4) {
                    // 未通过的审批到此结束，不再去处理订单价格
                    if (notExistProcessingItemBatchApproval && !orderStatusUpdated) {

                        this.updateStatus(orderDO.getOrderId(), null, null, null, null, null, 0, this.getAuditResult(result, orderApprovalDO.getType()));

                        orderStatusUpdated = true;
                    }
                }
            }

            //取消后， 不执行后面的业务。直接return
            if (result == 3 || result == 4) {
                return;
            }

            // 审批通过后处理订单价格
            Integer logType = 0;
            if (Objects.equals(orderApprovalDO.getType(), OrderApprovalTypeEnum.DISCOUNT_APPLY_BATCH.getValue())) {
                logType = 11;
            } else if (Objects.equals(orderApprovalDO.getType(), OrderApprovalTypeEnum.ADMIN_DISCOUNT_BATCH.getValue())) {
                logType = 12;
            }
            for (OrderSpecialBatchApplyOrderItemDetailVO batchApplyOrderItemDetailVO : batchApplyOrderItemDetailVOList) {
                // 校验是否有已核销的应收单
                receivableService.verificationReceivableIsWriteOff(null, batchApplyOrderItemDetailVO.getOrderItemId());
                orderItemDOList = orderItemDOList.stream().peek(oi -> {
                    if (Objects.equals(oi.getOrderItemId(), batchApplyOrderItemDetailVO.getOrderItemId())) {
                        // 需要标记为固定成交单价， 且需要重置批量加价金额为0
                        oi.setOneClearanceFreight(batchApplyOrderItemDetailVO.getClearanceFreight());
                        oi.setOneSeaFreight(batchApplyOrderItemDetailVO.getFreight());
                        oi.setMarkupSeaFreight(BigDecimal.ZERO);
                        oi.setMarkupClearanceFreight(BigDecimal.ZERO);
                        oi.setIsPriced(Boolean.TRUE);
                        oi.setSpecialPriceType(Boolean.TRUE);
                    }
                }).collect(Collectors.toList());
            }

            orderBusinessService.addOrderTimeLog(orderDO.getStatus(), orderDO, logType);
            this.specialOrderHandle(orderDO, orderItemDOList);
            this.updateStatus(orderDO.getOrderId(), null, null, null, null, null, 0, this.getAuditResult(result, orderApprovalDO.getType()));

        } else {
            OrderSpecialApplyVO specialApplyVO = JSONObject.parseObject(orderApprovalDO.getDetails(), OrderSpecialApplyVO.class);
            specialApplyVO.setApplyStatus(result);
            specialApplyVO.setApplyResult(taskResp.getComment());
            // 查询最后审核的详细信息
            orderApprovalDO.setDetails(JSONObject.toJSONString(specialApplyVO));
            orderApprovalDO.setFinishBy(String.valueOf(taskResp.getAssigneeUser().getId()));
            orderApprovalDO.setFinishTime(new Date());
            orderApprovalDO.setProcessingResults(taskResp.getComment());
            // 更新审批结果
            orderApprovalMapper.updateById(orderApprovalDO);
            // 开始根据审批结果更新订单及订单项信息
            int count;
            List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderDO.getOrderId()));
            if (CollectionUtil.isEmpty(orderItemDOList)) {
                return;
            }
            if (specialApplyVO.getApplyType() != 4 && specialApplyVO.getApplyType() != 5 && specialApplyVO.getApplyType() != 29) {
                // 查询特价申请的审批类型是否有在处理中的
                count = orderApprovalMapper.processingItemApproval(specialApplyVO.getOrderItemId(), specialApplyVO.getOrderId(), Arrays.asList(1, 2, 3));
                if (count == 0) {
                    // 有正在处理中的申请
                    orderItemDOList = orderItemDOList.stream().peek(oi -> {
                        if (Objects.equals(oi.getOrderItemId(), specialApplyVO.getOrderItemId())) {
                            oi.setItemStatus(0);
                        }
                    }).collect(Collectors.toList());
                }
            } else {
                // 查询特价申请的审批类型是否有在处理中的
                count = orderApprovalMapper.processingItemApproval(null, orderDO.getOrderId(), Arrays.asList(4, 5));
                if (count == 0) {
                    // 有正在处理中的申请
                    orderItemDOList = orderItemDOList.stream().peek(orderItemDO -> orderItemDO.setItemStatus(0)).collect(Collectors.toList());
                }
            }
            if (result == 3 || result == 4) {
                // 未通过的审批到此结束，不再去处理订单价格
                if (count == 0) {
                    this.updateStatus(orderDO.getOrderId(), null, null, null, null, null, 0, this.getAuditResult(result, orderApprovalDO.getType()));
                }
                return;
            }
            Integer logType = 0;
            boolean isClearSpecialVWeight = false;
            // 审批通过后处理订单价格
            if (orderApprovalDO.getType() == 2 || orderApprovalDO.getType() == 1) {
                logType = orderApprovalDO.getType() == 2 ? 3 : 4;
                // 校验是否有已核销的应收单
                receivableService.verificationReceivableIsWriteOff(null, specialApplyVO.getOrderItemId());
                orderItemDOList = orderItemDOList.stream().peek(oi -> {
                    if (Objects.equals(oi.getOrderItemId(), specialApplyVO.getOrderItemId())) {
                        // 需要标记为固定成交单价， 且需要重置批量加价金额为0
                        oi.setOneClearanceFreight(specialApplyVO.getClearanceFreight());
                        oi.setOneSeaFreight(specialApplyVO.getFreight());
                        oi.setMarkupSeaFreight(BigDecimal.ZERO);
                        oi.setMarkupClearanceFreight(BigDecimal.ZERO);
                        oi.setIsPriced(Boolean.TRUE);
                        oi.setSpecialPriceType(Boolean.TRUE);
                    }
                }).collect(Collectors.toList());
            }
            if (orderApprovalDO.getType() == 3) {
                logType = 9;
                // 校验是否有已核销的应收单
                receivableService.verificationReceivableIsWriteOff(null, specialApplyVO.getOrderItemId());
                orderItemDOList = orderItemDOList.stream().peek(oi -> {
                    if (Objects.equals(oi.getOrderItemId(), specialApplyVO.getOrderItemId())) {
                        BigDecimal saleAmount = oi.getOneSeaFreight().subtract(oi.getPlainCommission()).add(specialApplyVO.getLightCommissionAmount());
                        oi.setCommissionType(specialApplyVO.getCommissionType());
                        oi.setHiddenCommission(specialApplyVO.getShadeCommissionAmount());
                        oi.setPlainCommission(specialApplyVO.getLightCommissionAmount());
                        oi.setOneSeaFreight(saleAmount);
                        oi.setSpecialCommission(Boolean.TRUE);// 特价佣金设置
                    }
                }).collect(Collectors.toList());
            }
            // 重泡货优惠业务
            if (orderApprovalDO.getType() == 4) {
                logType = 5;
                // 校验是否有已核销的应收单
                receivableService.verificationReceivableIsWriteOff(orderDO.getOrderId(), null);
                orderDO.setWeightUnit(specialApplyVO.getWVolume());
                // 这里不需要对可能的柜号或提单号进行更新
                orderDO.setContainerNumber(null);
                orderDO.setTidanNo(null);
                orderMapper.updateById(orderDO);
                orderItemDOList = orderItemDOList.stream().peek(oi -> {
                    WarehouseInInfoVO warehouseInInfoVO = oi.getWarehouseInInfoVO();
                    if (Objects.nonNull(warehouseInInfoVO) && Objects.nonNull(warehouseInInfoVO.getVolume())) {
                        // 订单项重新计算重货方数
                        oi.setWVolume(warehouseInInfoVO.getWeight().divide(specialApplyVO.getWVolume(), 2, RoundingMode.HALF_UP));
                    }
                }).collect(Collectors.toList());
                // 判断是否需要生成重货异常
                if (specialApplyVO.getWVolume() != null && orderDO.getSumWeight() != null && (TransportTypeShortEnum.SEA_CONTAINER.getValue().equals(orderDO.getTransportId()) || TransportTypeShortEnum.MARINE_CONTAINER.getValue().equals(orderDO.getTransportId()))) {
                    // 计算（入仓时订单总重量大于订单总方数，总重量/750（取自当前用户的重货标准）>总体积）
                    BigDecimal zhongCbm = orderDO.getSumWeight().divide(specialApplyVO.getWVolume(), 2, RoundingMode.HALF_UP);
                    List<OrderExceptionDO> pendHeavyExceptionList = orderExceptionService.getPendingOrderExceptionByOrderIdAndOrderItemIdAndExceptionKey(orderDO.getOrderId(), null, OrderExceptionEnum.ORDER_HEAVY_CARGO_EXCEPTION.getKey());
                    if (zhongCbm.compareTo(orderDO.getSumVolume()) > 0) {
                        ///重货异常
                        String descZh = String.format("该订单是重货订单, 重货方数(总)：%s", zhongCbm);
                        String descEn = String.format("It's heavy order, value(sum)：%s", zhongCbm);
                        if (CollectionUtil.isEmpty(pendHeavyExceptionList) || pendHeavyExceptionList.size() == 0) {
                            OrderExceptionCreateReqVO orderExceptionCreateReqVO = this.genOrderException(orderDO.getOrderId(), orderDO, null, null, OrderExceptionEnum.ORDER_HEAVY_CARGO_EXCEPTION, descZh, descEn);
                            orderExceptionService.createOrderException(orderExceptionCreateReqVO);
                        } else {
                            // 如果有异常则更新说明
                            OrderExceptionDO orderExceptionDO = pendHeavyExceptionList.get(0);
                            orderExceptionDO.setOrderExceptionRemark(JSONObject.toJSONString(OrderExceptionDescVO.builder().descZh(descZh).descEn(descEn).build()));
                            orderExceptionService.updateById(orderExceptionDO);
                        }
                        //更新订单为重货
                        this.updateOrderType(orderDO.getOrderId(), 2);
                        orderDO = orderMapper.selectById(orderDO.getOrderId());

                    } else {
                        orderExceptionService.autoProcessException(orderDO.getOrderId(), null, OrderExceptionEnum.ORDER_HEAVY_CARGO_EXCEPTION, String.format("申请重货优惠%sKg/CBM审批通过，订单非重货，系统处理动处理", specialApplyVO.getWVolume()), OrderExceptionResult.ORDER_BULKY_CARGO_EXCEPTION_RESULT.GENERAL_CARGO);

                        //更新订单为普货
                        this.updateOrderType(orderDO.getOrderId(), 1);
                        orderDO = orderMapper.selectById(orderDO.getOrderId());
                    }
                }
            }
            if (orderApprovalDO.getType() == 5 || orderApprovalDO.getType() == 29) {
                logType = 6;
                // 校验是否有已核销的应收单
                receivableService.verificationReceivableIsWriteOff(orderDO.getOrderId(), null);
                if (orderApprovalDO.getType() == 5) {
                    // 泡货标准优惠
                    orderDO.setVolumeUnit(specialApplyVO.getVWeight());
                    orderItemDOList = orderItemDOList.stream().peek(oi -> {
                        WarehouseInInfoVO warehouseInInfoVO = oi.getWarehouseInInfoVO();
                        if (Objects.nonNull(warehouseInInfoVO) && Objects.nonNull(warehouseInInfoVO.getVolume())) {
                            // 订单项重新计算泡货重量
                            oi.setVWeight(warehouseInInfoVO.getVolume().multiply(specialApplyVO.getVWeight()));
                        }
                    }).collect(Collectors.toList());
                    if (orderDO.getSpecialVWeight().compareTo(BigDecimal.ZERO) > 0) {
                        // 如果泡货标准优惠申请通过时，有泡重优惠值，则将其重置，以保证以最新的泡货标准优惠来执行计算业务
                        orderDO.setSpecialVWeight(BigDecimal.ZERO);
                        isClearSpecialVWeight = true;
                    }
                } else {
                    // 泡重计算结果优惠
                    orderDO.setVWeight(specialApplyVO.getVWeight());
                    orderDO.setSpecialVWeight(specialApplyVO.getVWeight());
                }
                // 这里不需要对可能的柜号或提单号进行更新
                orderDO.setContainerNumber(null);
                orderDO.setTidanNo(null);
                orderMapper.updateById(orderDO);

                // 此处订单打包后 判断是否需要生成泡货异常
                if (orderDO.getAirShipment() == 4) {
                    if (specialApplyVO.getVWeight() != null && orderDO.getSumVolume() != null && (TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue().equals(orderDO.getTransportId()) || TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue().equals(orderDO.getTransportId()))) {
                        // 计算（入仓时订单总重量大于订单总方数，总重量/750（取自当前用户的重货标准）>总体积）
                        BigDecimal paoKg = orderApprovalDO.getType() == 5 ? orderDO.getSumVolume().multiply(specialApplyVO.getVWeight()) : specialApplyVO.getVWeight();
                        paoKg = BigDecimalUtils.convertWv(paoKg);
                        List<OrderExceptionDO> bulkyExceptionList = orderExceptionService.getOrderExceptionByOrderIdAndOrderItemIdAndExceptionKey(orderDO.getOrderId(), null, OrderExceptionEnum.ORDER_BULKY_CARGO_EXCEPTION.getKey());
                        List<OrderExceptionDO> pendBulkyExceptionList = new ArrayList<>();
                        if (CollectionUtil.isNotEmpty(bulkyExceptionList)) {
                            pendBulkyExceptionList = bulkyExceptionList.stream().filter(ex -> ex.getOrderExceptionStatus() == 0 || ex.getOrderExceptionStatus() == 1).collect(Collectors.toList());
                        }
                        if (paoKg.compareTo(orderDO.getSumWeight()) > 0) {
                            // 泡货异常
                            String descZh = String.format("该订单是泡货订单, 泡货重量(总)：%sKg", paoKg);
                            String descEn = String.format("It's bubble order, weight(sum)：%s", paoKg);
                            if ((CollectionUtil.isEmpty(pendBulkyExceptionList) || pendBulkyExceptionList.size() == 0)) {
                                if (orderApprovalDO.getType() == 5 || bulkyExceptionList.size() == 0) {
                                    // 当订单产生过泡货异常，且是泡重优惠申请时，不再产生泡货异常，泡重优惠申请只是修改订单整体收费值的操作
                                    OrderExceptionCreateReqVO orderExceptionCreateReqVO = this.genOrderException(orderDO.getOrderId(), orderDO, null, null, OrderExceptionEnum.ORDER_BULKY_CARGO_EXCEPTION, descZh, descEn);
                                    orderExceptionService.createOrderException(orderExceptionCreateReqVO);
                                }
                            } else {
                                // 如果有异常则更新说明
                                OrderExceptionDO orderExceptionDO = pendBulkyExceptionList.get(0);
                                orderExceptionDO.setOrderExceptionRemark(JSONObject.toJSONString(OrderExceptionDescVO.builder().descZh(descZh).descEn(descEn).build()));
                                orderExceptionService.updateById(orderExceptionDO);
                            }
                            //更新订单为泡货
                            this.updateOrderType(orderDO.getOrderId(), 3);
                            orderDO = orderMapper.selectById(orderDO.getOrderId());
                        } else {
                            orderExceptionService.autoProcessException(orderDO.getOrderId(), null, OrderExceptionEnum.ORDER_BULKY_CARGO_EXCEPTION, String.format("申请泡货优惠%sKg/CBM审批通过，订单非泡货，系统处理动处理，操作人=" + SecurityFrameworkUtils.getLoginUserNickName(), specialApplyVO.getVWeight()), OrderExceptionResult.ORDER_BULKY_CARGO_EXCEPTION_RESULT.GENERAL_CARGO);
                            //更新订单为普货
                            this.updateOrderType(orderDO.getOrderId(), 1);
                            orderDO = orderMapper.selectById(orderDO.getOrderId());
                        }
                    }
                }
            }
            orderBusinessService.addOrderTimeLog(orderDO.getStatus(), orderDO, logType);
            this.specialOrderHandle(orderDO, orderItemDOList);
            this.updateStatus(orderDO.getOrderId(), null, null, null, null, null, 0, this.getAuditResult(result, orderApprovalDO.getType()));
            if (isClearSpecialVWeight) {
                // 当泡货标准优惠申请通过后，如果有泡重优惠，则重置泡重优惠，保证以当前最新申请通过的泡货标准优惠来执行计算
                orderBusinessService.addOrderOperateLog(orderDO.getOrderId(), "订单泡货优惠通过后重置泡重优惠值", null);
            }
        }
    }

    private void approvalUpdateOrder(OrderBackVO orderBackVO, Long userId) {
        OrderConsignorBackVO consignorVO = orderBackVO.getConsignorVO();
        OrderConsigneeBackVO consigneeVO = orderBackVO.getConsigneeVO();

        OrderConsignorDO orderConsignorDO = orderConsignorService.getById(consignorVO.getId());
        OrderConsigneeDO orderConsigneeDO = null;
        if (Objects.nonNull(consigneeVO)) {
            orderConsigneeService.getById(consigneeVO.getId());
        }
        //
        boolean isConsignorChange = orderConsignorDO != null && !Objects.equals(consignorVO.getCustomerId(), orderConsignorDO.getCustomerId());
        boolean isConsigneeChange = orderConsigneeDO != null && Objects.nonNull(consigneeVO) && !Objects.equals(consigneeVO.getCustomerId(), orderConsigneeDO.getCustomerId());

        // 收发货人信息变更
        OrderConsignorDO consignorDO = OrderConsignorConvert.INSTANCE.convert(consignorVO);
        orderConsignorService.updateById(consignorDO);
        OrderConsigneeDO consigneeDO = null;
        if (Objects.nonNull(consigneeVO)) {
            consigneeDO = OrderConsigneeConvert.INSTANCE.convert(consigneeVO);
        }
        // 控货订单发货人无收货人属性变动，需要清空订单收货人信息
        Boolean isLimitUpdateConsignee = Boolean.FALSE;
        if (orderBackVO.getIsChargeNoConsignee()) {
            if (Objects.nonNull(consigneeDO)) {
                orderConsigneeService.removeById(consigneeDO.getId());
            }
        } else {
            if (Objects.nonNull(consigneeDO)) {
                orderConsigneeService.updateById(consigneeDO);
                if (orderBackVO.getIsCargoControl()) {
                    // 控货订单有收货人则限制修改收货人
                    isLimitUpdateConsignee = Boolean.TRUE;
                }
            }
        }
        // 始发地目的地更新
        OrderDepartureDO departureDO = OrderDepartureConvert.INSTANCE.convert(orderBackVO.getOrderDepartureVO());
        orderDepartureService.updateById(departureDO);
        OrderObjectiveDO objectiveDO = OrderObjectiveConvert.INSTANCE.convert(orderBackVO.getOrderObjectiveVO());
        orderObjectiveService.updateById(objectiveDO);
        OrderDO orderDO = OrderConvert.INSTANCE.convert(orderBackVO);
        OrderDO oldOrder = orderMapper.selectById(orderDO.getOrderId());
        if (orderBackVO.getIsException()) {
            orderDO.setHandlerChannelAttrException(false);
        }
        orderDO.setIsLimitUpdateConsignee(isLimitUpdateConsignee);
        orderDO.setOrderNo(oldOrder.getOrderNo());
        String oldOrderNo = oldOrder.getOrderNo(); // 临时保存旧的订单编号
        boolean isDisassociation = false;
        if (orderBackVO.getIsResetOrderNo()) {
            // TODO 需要重新生成订单编号
            // 订单始发地信息
            if (Objects.isNull(departureDO) || !Objects.equals(departureDO.getDepartureId(), orderDO.getDepartureId())) {
                // 查询始发地与目的地信息
                RegionDO departure = regionService.getRegion(orderDO.getDepartureId());
                if (Objects.isNull(departure) || (!StrUtil.equals(departure.getType(), "2") && !StrUtil.equals(departure.getType(), "3"))) {
                    throw exception(DEPARTURE_NOT_EXISTS);
                }
                if (Objects.isNull(departureDO)) {
                    departureDO = new OrderDepartureDO();
                }
                departureDO.setDepartureId(orderDO.getDepartureId());
                departureDO.setDeparture(JSONObject.toJSONString(departure));
            }
            // 订单目的地信息
            // 目的地发生变更,则重新生成订单号, 或状态从草稿变为下单
            RegionDO objective = regionService.getRegion(orderDO.getObjectiveId());
            if (Objects.isNull(objectiveDO)) {
                objectiveDO = new OrderObjectiveDO();
            }
            objectiveDO.setObjectiveId(orderDO.getObjectiveId());
            objectiveDO.setObjective(JSONObject.toJSONString(objective));
            String newOrderNo = orderBusinessService.saveOrUpdateOrderNo(objective, orderDO.getTransportId(), orderDO.getIsExternalWarehouse(),
                    StringUtils.isNotBlank(orderDO.getType()) && orderDO.getType().contains("1"));
            applicationContext.publishEvent(new OfferUpdateOrderNumberEvent(orderDO.getOrderId(), newOrderNo));
            orderDO.setOrderNo(newOrderNo);
            if (!StringUtils.equals(oldOrderNo, orderDO.getOrderNo())) {
                orderDO.setNoChargeRecord(StringUtils.isNotBlank(oldOrder.getNoChargeRecord()) ?
                        (oldOrder.getNoChargeRecord() + StrUtil.COMMA + oldOrderNo) : oldOrderNo);
                chargeOrderNo(orderDO, oldOrderNo);
            }
            // 当订单编号发生改变时，肯定是关联订单的条件发生改变了，需要解除原单的关联关系
            isDisassociation = true;
        }
        // 获取最早入仓时间，当入仓时间大于三天，则不允许再修改当前客户归属
        OrderWarehouseInDO warehouseInDO = orderWarehouseInMapper.selectOne(new LambdaQueryWrapper<OrderWarehouseInDO>()
                .eq(OrderWarehouseInDO::getOrderId, oldOrder.getOrderId())
                .orderByAsc(OrderWarehouseInDO::getInTime).last("limit 1"));
        if (Objects.isNull(warehouseInDO)) {
            throw exception(ORDER_NOT_WAREHOUSE_IN);
        }
        if (orderBackVO.getIsCreateCustomerServiceException()) {
            // TODO 这里会有一个问题，当审批通过时，该客户分配了客户经理并接收了，或者未接收的客户经理被接收了是否还产生异常
            String descZh = orderBackVO.getDescZh();
            String descEn = orderBackVO.getDescEn();
            OrderExceptionCreateReqVO orderExceptionCreateReqVO = this.genOrderException(orderBackVO.getOrderId(), orderBackVO, null, orderBackVO.getCustomerId(), OrderExceptionEnum.NOT_CUSTOMER_SERVICE_EXCEPTION,
                    descZh, descEn);
            orderExceptionService.createOrderException(orderExceptionCreateReqVO);
        }
        // 这里可能因为修改内容不触发计价业务，而提交审批内容的同时，提交了不用审批的修改货值，导致费用清单变更，所以这里需要同步当前数据库的费用清单
        orderDO.setCost(oldOrder.getCost());
        // 在这中间可能有订单的入仓子状态变更，例如调仓等操作，需要同步当前数据库订单状态,因为订单审批同时只能有一个，所以审批状态肯定是实时的，只需要同步其他状态
        orderDO.setStatus(oldOrder.getStatus());// 主状态
        orderDO.setInWarehouseState(oldOrder.getInWarehouseState());// 入仓
        orderDO.setShipmentState(oldOrder.getShipmentState());// 出货
        orderDO.setAbnormalState(oldOrder.getAbnormalState());// 异常
        orderDO.setCargoControlStatus(oldOrder.getCargoControlStatus());// 控货
        // 这中间可能有异常产生或已处理，需要实时同步异常状态
        orderDO.setAbnormalState(oldOrder.getAbnormalState());
        Date now = new Date();
        orderDO.setUpdateTime(now);
        if (orderBackVO.getIsResetPrice()) {
            orderDO.setHandlerChannelAttrException(false);
        }
        // 这里不需要对可能的柜号或提单号进行更新
        orderDO.setContainerNumber(null);
        orderDO.setTidanNo(null);
        orderMapper.updateById(orderDO);
        // 处理控货信息
        handleOrderCargoControl(consignorDO, orderDO);
        // 重新计价
        if (orderBackVO.getIsResetPrice()) {
            List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderDO.getOrderId()));
            orderItemDOList = orderItemDOList.stream().peek(it -> {
                // 重置异常
                it.setHandlerChannelAttrException(false);
                it.setIsHandlerOrderInquiryException(false);
                // 重置特价
                it.setSpecialPriceType(false);
                it.setChannelManualPricing(false);
                it.setSplitCustomPriceType(false);
            }).collect(Collectors.toList());
            // 强制重新定价, 则需要将特价属性都重置
            orderBusinessService.costCalculation(String.valueOf(userId), orderDO, consignorDO.getCustomerId(), Objects.isNull(consigneeDO) ? 0L : consigneeDO.getCustomerId(),
                    consignorDO.getCustomerContactsId(), Objects.isNull(consigneeDO) ? 0L : consigneeDO.getCustomerContactsId(), orderItemDOList, 10);
        } else if (orderBackVO.getIsCheckCoupon()) {
            // 如果没有重新计价，这里就需要对订单优惠活动进行检查，是否需要重新匹配新的优惠
            List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderDO.getOrderId()));
            // 是否需要检查优惠卷(如果满足当前优惠卷，则继续使用(即使过期也可以)，如果不满足则匹配最新的优惠(排除过期))
            orderBusinessService.costCalculation(String.valueOf(userId), orderDO, consignorDO.getCustomerId(), Objects.isNull(consigneeDO) ? 0L : consigneeDO.getCustomerId(),
                    consignorDO.getCustomerContactsId(), Objects.isNull(consigneeDO) ? 0L : consigneeDO.getCustomerContactsId(), orderItemDOList, 51);
        }
        orderBusinessService.addOrderTimeLog(orderDO.getStatus(), orderDO, 7, now, now);
        // 空运相关订单处理业务
        if (Objects.equals(TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue(),
                orderDO.getTransportId())
                || Objects.equals(TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue(), orderDO.getTransportId())) {
            // 空运渠道异常处理，当编辑订单后，订单渠道补充完，则调用处理空运渠道异常
            if ((Objects.isNull(oldOrder.getChannelId()) || oldOrder.getChannelId() == 0L) && Objects.nonNull(orderDO.getChannelId()) && orderDO.getChannelId() > 0) {
                orderExceptionService.orderChannelExceptionCallback(oldOrder.getOrderId());
            }
            if (Objects.nonNull(oldOrder.getChannelId()) && oldOrder.getChannelId() > 0L && (Objects.isNull(orderDO.getChannelId()) || 0 == orderDO.getChannelId())) {
                // 当前空运或海空联运订单下单时，没有渠道id，则生成渠道异常
                OrderExceptionCreateReqVO orderExceptionCreateReqVO = this.genOrderException(orderDO.getOrderId(), orderDO, null, null, OrderExceptionEnum.CHANNEL_EXCEPTION,
                        "未选择线路渠道", "No route channel selected");
                orderExceptionService.createOrderException(orderExceptionCreateReqVO);
            }
            if ((Objects.isNull(oldOrder.getChannelId()) &&
                    Objects.nonNull(orderDO.getChannelId()))
                    || (Objects.nonNull(oldOrder.getChannelId())
                    && Objects.nonNull(orderDO.getChannelId()) &&
                    oldOrder.getChannelId() != orderDO.getChannelId())) {
                // 渠道变更
                OrderDto orderDto = new OrderDto();
                BeanUtils.copyProperties(orderDO, orderDto);
                applicationContext.publishEvent(
                        new WarehouseInOrderChangeChannelEvent(orderDto));
            }
        }
        orderBusinessService.addOrderTimeLog(orderDO.getStatus(), orderDO, 7);
        this.updateStatus(orderDO.getOrderId(),
                null, null, null,
                null, null, 0,
                this.getAuditResult(orderBackVO.getApplyStatus(), ORDER_UPDATE.getValue()), null, null, JSONObject.toJSONString(orderBackVO.getApplyInfoList()));

        if (orderBackVO.getIsDrawee()) {

            // 查询订单已添加的费用类型
            List<ReceivableDO> receivableDOList = receivableService.list(new LambdaQueryWrapper<ReceivableDO>().eq(ReceivableDO::getOrderId, orderDO.getOrderId()).eq(ReceivableDO::getDeleted, false));
            if (orderBackVO.getDrawee() == 3) {
                // 付款人信息变更，需要将应收单的付款人信息变更
                List<CustomDraweeVO> customDraweeVOList = orderBackVO.getCustomDraweeVOList();
                if (CollectionUtil.isNotEmpty(receivableDOList) && CollectionUtil.isNotEmpty(customDraweeVOList)) {
                    for (ReceivableDO receivableDO : receivableDOList) {
                        CustomDraweeEnum customDraweeEnum = CustomDraweeEnum.valueOf(receivableDO.getFeeType());
                        if (Objects.nonNull(customDraweeEnum)) {
                            CustomDraweeVO customDraweeVO = customDraweeVOList.stream()
                                    .filter(vo -> Objects.equals(vo.getName(), customDraweeEnum.getKey())).findFirst().orElse(null);
                            if (Objects.nonNull(customDraweeVO)) {
                                receivableService.update(new LambdaUpdateWrapper<ReceivableDO>()
                                        .set(ReceivableDO::getPaymentUser, customDraweeVO.getValue())
                                        .eq(ReceivableDO::getId, receivableDO.getId()));
                            }
                        }
                    }
                }
            } else {
                if (CollectionUtil.isNotEmpty(receivableDOList)) {
                    for (ReceivableDO receivableDO : receivableDOList) {
                        receivableService.update(new LambdaUpdateWrapper<ReceivableDO>()
                                .set(ReceivableDO::getPaymentUser, orderBackVO.getDrawee())
                                .eq(ReceivableDO::getId, receivableDO.getId()));
                    }
                }
            }
        }

        try {
            //发货人
            if (isConsignorChange && consignorVO.getCustomerId() != null) {
                customerService.updateCustomerStatusByExistedOrderAndOffer(consignorVO.getCustomerId(), true);
            }
            //收货人
            if (isConsigneeChange && consigneeVO.getCustomerId() != null) {
                customerService.updateCustomerStatusByExistedOrderAndOffer(consigneeVO.getCustomerId(), true);
            }

        } catch (Exception e) {
            log.error("更新收发货人状态时出现异常", e);
        }
        if (isDisassociation) {
            orderGuanlianService.deleteRelationByOrderId(orderDO.getOrderId());
        }
        // TODO 当运输方式出现变更时需要重置入仓业务
        if (orderBackVO.getIsTransport()) {
            applicationContext.publishEvent(
                    new WarehouseInOrderChangeTransportEvent(orderDO.getOrderId()));
        }
    }


    private void handleOrderCargoControl(OrderConsignorDO consignorDO, OrderDO orderDO) {
        if (orderDO.getIsCargoControl()) {
            // 控货订单
            long count = orderCargoControlMapper.selectCount(new LambdaQueryWrapper<OrderCargoControlDO>()
                    .eq(OrderCargoControlDO::getOrderId, orderDO.getOrderId())
                    .eq(OrderCargoControlDO::getIsActual, 1));
            if (count == 0) {
                // 没有控货人，则新增发货人为默认控货人
                OrderCargoControlDO orderCargoControlDO = new OrderCargoControlDO();
                BeanUtils.copyProperties(consignorDO, orderCargoControlDO);
                orderCargoControlDO.setId(null); // 置空主键ID
                orderCargoControlDO.setDialCode(Integer.valueOf(consignorDO.getCountryCode()));
                orderCargoControlDO.setIso2(consignorDO.getCountryAbbreviation());
                orderCargoControlDO.setOrderNo(orderDO.getOrderNo());
                orderCargoControlDO.setTidanNo(orderDO.getTidanNo());
                orderCargoControlDO.setCreator(orderDO.getUpdater());
                orderCargoControlDO.setCreateTime(new Date());
                orderCargoControlDO.setIsActual(Boolean.TRUE);
                orderCargoControlMapper.insert(orderCargoControlDO);
            }
        } else {
            // 非控货订单
            long count = orderCargoControlMapper.selectCount(new LambdaQueryWrapper<OrderCargoControlDO>()
                    .eq(OrderCargoControlDO::getOrderId, orderDO.getOrderId()));
            if (count > 0) {
                // 有控货人，则删除控货人信息
                orderCargoControlMapper.update(null, new LambdaUpdateWrapper<OrderCargoControlDO>()
                        .set(OrderCargoControlDO::getDeleted, Boolean.TRUE)
                        .eq(OrderCargoControlDO::getOrderId, orderDO.getOrderId()));
            }
        }
    }


    /**
     * 订单编号变更业务
     *
     * @param orderDO    新的订单信息
     * @param oldOrderNo 原订单编号
     */
    private void chargeOrderNo(OrderDO orderDO, String oldOrderNo) {
        // 对比订单编号是否被修改, 且不是草稿订单编号变更为正式订单号时，需要同步修改订单审批和异常业务中的冗余订单号
        // TODO 订单审批业务是否修改或弃用待定
        // 获取订单审批任务
//            List<OrderApprovalDO> approvalDOList = orderApprovalMapper.selectList(new LambdaQueryWrapper<OrderApprovalDO>().eq(OrderApprovalDO::getOrderId, orderDO.getOrderId()));
//            for (OrderApprovalDO orderApprovalDO : approvalDOList) {
//                // 订单编号变更，需要取消进行中的审批
//            }
        // 处理应收单中的订单编号
        receivableService.update(new LambdaUpdateWrapper<ReceivableDO>()
                .set(ReceivableDO::getOrderNo, orderDO.getOrderNo())
                .eq(ReceivableDO::getOrderId, orderDO.getOrderId()));

        // 处理异常业务中的订单号变更
        orderExceptionService.update(new LambdaUpdateWrapper<OrderExceptionDO>()
                .set(OrderExceptionDO::getOrderNumber, orderDO.getOrderNo())
                .eq(OrderExceptionDO::getOrderId, orderDO.getOrderId()));

    }

    private void specialOrderHandle(OrderDO orderDO, List<OrderItemDO> orderItemDOList) {
        String userId = String.valueOf(SecurityFrameworkUtils.getLoginUserId());
        OrderConsignorDO orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsignorDO::getId).last("limit 1"));
        OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsigneeDO::getId).last("limit 1"));
        orderBusinessService.costCalculation(userId, orderDO, orderConsignorDO.getCustomerId(), Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerId(),
                orderConsignorDO.getCustomerContactsId(), Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerContactsId(), orderItemDOList, 7);
    }

    private String getAuditResult(Integer result, Integer type) {
        OrderApprovalTypeResultEnum orderApprovalTypeResultEnum = OrderApprovalTypeResultEnum.typeAndResultOf(type, result);
        return Objects.isNull(orderApprovalTypeResultEnum) ? "未知审批" : orderApprovalTypeResultEnum.getDesc();
    }

    @Override
    public void deleteOrder(Long orderId) {
        OrderDO orderDO = orderMapper.selectById(orderId);
        if (Objects.isNull(orderDO)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        if (orderDO.getStatus() != 0 && orderDO.getStatus() != 88
                && !Objects.equals(orderDO.getStatus(), OrderStatusEnum.MERGED_ORDER.getValue())
                && !Objects.equals(orderDO.getStatus(), OrderStatusEnum.SPLIT_ORDER.getValue())) {
            throw exception(ORDER_NOT_CANCEL_OR_DRAFT_STATUS);
        }
        // 更新订单操作日志
        orderBusinessService.addOrderOperateLog(orderId, "订单删除", null);
        // 删除订单的异常信息
        orderExceptionService.update(new LambdaUpdateWrapper<OrderExceptionDO>().set(OrderExceptionDO::getDeleted, Boolean.TRUE).set(OrderExceptionDO::getUpdateTime, new Date()).set(OrderExceptionDO::getUpdater, String.valueOf(SecurityFrameworkUtils.getLoginUserId())).eq(OrderExceptionDO::getOrderId, orderId));
        // 删除订单
        this.update(new LambdaUpdateWrapper<OrderDO>().set(OrderDO::getDeleted, Boolean.TRUE).set(OrderDO::getUpdateTime, new Date()).set(OrderDO::getUpdater, String.valueOf(SecurityFrameworkUtils.getLoginUserId())).eq(OrderDO::getOrderId, orderId));
    }

    @Override
    public void deleteOrderByParentOrderId(Long parentOrderId,
                                           List<OrderBackInfoDto> orderBackInfoDtoList) {

        // 置空母订单的拆单时间
        this.update(new LambdaUpdateWrapper<OrderDO>().set(OrderDO::getSplitTime,
                null).eq(OrderDO::getOrderId, parentOrderId));
        // 查询相关子订单信息，并且删除子订单相关的记录，避免重新撤销拆单后再次拆单的数据重复
        if (CollectionUtil.isNotEmpty(orderBackInfoDtoList)) {
            List<Long> orderIds = new ArrayList<>();
            for (OrderBackInfoDto splitOrder : orderBackInfoDtoList) {
                Long splitOrderId = splitOrder.getOrderId();
                orderIds.add(splitOrderId);
                // 删除子拆单的操作日志
                orderOperateLogService.remove(new LambdaQueryWrapper<OrderOperateLogDO>().eq(OrderOperateLogDO::getOrderId, splitOrderId));
                // 删除子拆单的异常信息
                orderExceptionService.remove(new LambdaQueryWrapper<OrderExceptionDO>().eq(OrderExceptionDO::getOrderId, splitOrderId));
                // 删除子拆单的订单动态
                orderTimeMapper.delete(new LambdaQueryWrapper<OrderTimeDO>().eq(OrderTimeDO::getOrderId, splitOrderId));
                // 删除子拆单的订单项
                orderItemMapper.delete(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, splitOrderId));
                // 删除子拆单的始发地与目的地
                orderObjectiveService.remove(new LambdaQueryWrapper<OrderObjectiveDO>().eq(OrderObjectiveDO::getOrderId, splitOrderId));
                orderDepartureService.remove(new LambdaQueryWrapper<OrderDepartureDO>().eq(OrderDepartureDO::getOrderId, splitOrderId));
                // 删除子拆单的发货人与收货人
                orderConsignorService.remove(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, splitOrderId));
                orderConsigneeService.remove(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, splitOrderId));
                // 删除子拆单的入仓信息
                orderWarehouseInMapper.delete(new LambdaQueryWrapper<OrderWarehouseInDO>().eq(OrderWarehouseInDO::getOrderId, splitOrderId));
                // 删除子拆单的控货人信息
                orderCargoControlMapper.delete(new LambdaQueryWrapper<OrderCargoControlDO>().eq(OrderCargoControlDO::getOrderId, splitOrderId));
                // 删除子拆单的放货记录
                orderCargoControlPickMapper.delete(new LambdaQueryWrapper<OrderCargoControlPickDO>().eq(OrderCargoControlPickDO::getOrderId, splitOrderId));
            }

            // 处理关联关系
            orderGuanlianService.dealGuanlianByOrderId(parentOrderId, orderIds, 2);
            // 处理互斥关系
            orderMutualService.dealMutualByOrderId(parentOrderId,
                    orderIds, 2);
            // 物理删除订单 ,在所有业务执行完成后进行删除
            orderMapper.remove(orderIds);
        }
        // 恢复母订单可能的费用申请记录应收单
        List<OrderFeeApplicationDO> feeApplicationDOList = feeApplicationService.getFeeApplicationListByOrderId(parentOrderId);
        if (CollectionUtil.isNotEmpty(feeApplicationDOList)) {
            for (OrderFeeApplicationDO f : feeApplicationDOList) {
                if (Objects.nonNull(f.getReceivableId()) && f.getReceivableId() > 0) {
                    receivableService.revokeDeleteReceivableById(Long.valueOf(f.getReceivableId()));
                }
            }
        }
        // 删除订单
//        this.remove(new LambdaQueryWrapper<OrderDO>().eq(OrderDO::getParentOrderId, parentOrderId));
    }

    @Override
    public void recoveryOrder(Long orderId) {
        OrderDO orderDO = orderMapper.selectById(orderId);
        if (Objects.isNull(orderDO)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        if (orderDO.getStatus() != 88) {
            throw exception(ORDER_IS_CANCEL_STATUS);
        }
        // 取消恢复订单状态
        orderDO.setStatus(OrderStatusEnum.ORDER_PLACED.getValue());
        orderDO.setOldStatus(OrderStatusEnum.CANCEL.getValue());
        orderDO.setUpdateTime(new Date());
        orderDO.setUpdater(String.valueOf(SecurityFrameworkUtils.getLoginUserId()));
        orderMapper.updateById(orderDO);
        // 更新订单操作日志
        orderBusinessService.addOrderOperateLog(orderId, "订单恢复", null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrder(Long orderId) {
        OrderDO orderDO = orderMapper.selectById(orderId);
        if (Objects.isNull(orderDO)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        if (orderDO.getStatus() == 88) {
            // 已经取消
            throw exception(ORDER_NOT_CANCEL_STATUS);
        }
        if (!Objects.equals(orderDO.getStatus(), OrderStatusEnum.ORDER_PLACED.getValue())) {
            // 只能取消已下单待入仓的订单
            throw exception(ORDER_CANCEL_NOT_PLACED);
        }
        if (orderDO.getAuditType() != 0) {
            // 订单审批中
            throw exception(ORDER_IS_APPROVAL_IN_PROCESS);
        }
        List<OrderExceptionDO> orderExceptionDOList = orderExceptionService.getPendingOrderExceptionByOrderIdAndOrderItemIdAndExceptionKey(orderId, null, null);
        if (CollectionUtil.isNotEmpty(orderExceptionDOList)) {
            // 订单有异常, 需要将异常删除
            for (OrderExceptionDO orderExceptionDO : orderExceptionDOList) {
                // 取消订单时需要删除全部待处理异常，订单异常状态会在后面被重置为0
                orderExceptionService.cancelOrderException(orderExceptionDO.getId());
            }
        }
        // TODO 需要对使用的优惠券进行退回处理
        this.update(new LambdaUpdateWrapper<OrderDO>()
                .set(OrderDO::getOldStatus, OrderStatusEnum.ORDER_PLACED.getValue())
                .set(OrderDO::getStatus, OrderStatusEnum.CANCEL.getValue())
                .set(OrderDO::getAbnormalState, 0)
                .set(OrderDO::getUpdateTime, new Date())
                .set(OrderDO::getUpdater, String.valueOf(SecurityFrameworkUtils.getLoginUserId()))
                .eq(OrderDO::getOrderId, orderId));
        // 更新订单操作日志
        orderBusinessService.addOrderOperateLog(orderId, "取消订单", null);
        if (Objects.equals(orderDO.getTransportId(), TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue())) {
            orderBusinessService.addAirOrderTimeLog(orderDO, OrderAirTimeEnum.AIR_ORDER_CANCEL, null, null, null, null, null, null);
        } else if (Objects.equals(orderDO.getTransportId(), TransportTypeShortEnum.SEA_CONTAINER.getValue())) {
            orderBusinessService.addSeaOrderTimeLog(orderDO, OrderSeaTimeEnum.SEA_ORDER_CANCEL, null, null, null, null, null, null);
        }
    }

    @Override
    public void addOrderOtherFee(Long orderId, List<FeeDto> feeDtoList) {
        OrderDO orderDO = orderMapper.selectById(orderId);
        if (Objects.isNull(orderDO)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        feeDtoList = feeDtoList.stream().peek(feeDto -> feeDto.setFeeType(FeeTypeEnum.OTHER_FEE.getType())).collect(Collectors.toList());
        if (StringUtils.isNotBlank(orderDO.getCost())) {
            CostVO costVO = JSONObject.parseObject(orderDO.getCost(), CostVO.class);
            if (CollectionUtil.isNotEmpty(costVO.getFeeDtoList())) {
                for (FeeDto feeDto : costVO.getFeeDtoList()) {
                    if (Objects.equals(feeDto.getFeeType(), FeeTypeEnum.OTHER_FEE.getType())) {
                        feeDto.setAmount(feeDto.getAmount().add(feeDtoList.stream().filter(dto -> Objects.equals(feeDto.getCurrencyId(), dto.getCurrencyId())).map(FeeDto::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add)));
                    }
                }
            } else {
                costVO.setFeeDtoList(feeDtoList);
            }
            orderDO.setCost(JSONObject.toJSONString(costVO));
        } else {
            CostVO costVO = new CostVO();
            costVO.setFeeDtoList(feeDtoList);
            orderDO.setCost(JSONObject.toJSONString(costVO));
        }
        orderMapper.updateById(orderDO);
        // 更新订单操作日志
//        orderBusinessService.addOrderOperateLog(orderId, "订单添加其他费用操作", null);
    }

    @Override
    public void updateLadingBillNo(Long orderId, String orderLadingBillNo) {
        LambdaUpdateWrapper<OrderDO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(OrderDO::getOrderId, orderId);
        updateWrapper.set(OrderDO::getTidanNo, orderLadingBillNo);
        update(null, updateWrapper);
//        OrderDO orderDO = new OrderDO();
//        orderDO.setTidanNo(orderLadingBillNo);
//        orderMapper.update(orderDO,
//                new LambdaQueryWrapper<OrderDO>()
//                        .eq(OrderDO::getOrderId, orderId));
        // 更新订单操作日志
        orderBusinessService.addOrderOperateLog(orderId, "订单的提单编号更新操作", null);
    }


    @Override
    public void updateAdjustWarehouseId(Long orderId, Long adjustToStartWarehouseId, Long adjustToDestWarehouseId) {
        orderMapper.updateAdjustWarehouseId(orderId, adjustToStartWarehouseId, adjustToDestWarehouseId);
    }

    @Override
    public void updateDestAdjustWarehouseId(Long orderId, Long destAdjustToStartWarehouseId, Long
            destAdjustToDestWarehouseId) {
        orderMapper.updateDestAdjustWarehouseId(orderId, destAdjustToStartWarehouseId, destAdjustToDestWarehouseId);
    }


    @Override
    public void finishOrderWarehouseIn(Long orderId) {
        OrderDO orderDO = orderMapper.selectById(orderId);
        List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderId).eq(OrderItemDO::getDeleted, false));
        String userId = String.valueOf(SecurityFrameworkUtils.getLoginUserId());
        OrderConsignorDO orderConsignorDO =
                orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsignorDO::getId).last("limit 1"));
        OrderConsigneeDO orderConsigneeDO =
                orderConsigneeService.getOne(
                        new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsigneeDO::getId).last("limit 1"));
        // 2024-08-08 当订单入仓完成，需要校验订单业绩归属客户方，当前是否在公海，是则业绩归属客户经理为空，否不需要修改
        CustomerDO customerDO = customerService.getCustomer(orderDO.getCustomerId());
        if (Objects.nonNull(customerDO) && customerDO.getIsInOpenSea() && Objects.nonNull(customerDO.getEnterOpenSeaTime())) {
            orderDO.setSalesmanId(0L);
            orderDO.setDeptId(0L);
            orderDO.setIsInOpenSea(customerDO.getIsInOpenSea());
            orderMapper.updateById(orderDO);
        }
        orderBusinessService.costCalculation(userId,
                orderDO,
                orderConsignorDO.getCustomerId(),
                Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerId(),
                orderConsignorDO.getCustomerContactsId(),
                Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerContactsId(),
                orderItemDOList, 15);
    }

    @Override
    public void finishOrderWarehouseInUpdate(Long orderId) {
        OrderDO orderDO = orderMapper.selectById(orderId);
        List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderId).eq(OrderItemDO::getDeleted, false));
        String userId = String.valueOf(SecurityFrameworkUtils.getLoginUserId());
        OrderConsignorDO orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsignorDO::getId).last("limit 1"));
        OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsigneeDO::getId).last("limit 1"));
        // 更新所属客户经理(业务员)
//        if (Objects.isNull(orderDO.getParentOrderId()) || orderDO.getParentOrderId() == 0 || orderDO.getSplitSeparateOrder()) {
//            // 拆单子订单不执行客户经理分配规则，以原单为主
//            if (Objects.nonNull(orderDO.getCustomerId()) && orderDO.getCustomerId() > 0) {
//                addOrderCustomerService(orderDO, Objects.equals(orderConsignorDO.getCustomerId(), orderDO.getCustomerId()) ? 1 : 2);
//            }
//        }
        orderBusinessService.costCalculation(userId,
                orderDO,
                orderConsignorDO.getCustomerId(),
                Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerId(),
                orderConsignorDO.getCustomerContactsId(),
                Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerContactsId(),
                orderItemDOList,
                10);
    }

    @Override
    public void finishOrderSorting(String containerNumber, Collection<Long> orderIds) {
        List<OrderDO> orderDOList = new ArrayList<>();
        if (StringUtils.isNotBlank(containerNumber)) {
            orderDOList = orderMapper.selectList(new LambdaQueryWrapper<OrderDO>().eq(OrderDO::getContainerNumber, containerNumber));
        } else {
            orderDOList = orderMapper.selectList(new LambdaQueryWrapper<OrderDO>().in(OrderDO::getOrderId, orderIds));
        }
        for (OrderDO orderDO : orderDOList) {
            List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderDO.getOrderId()).eq(OrderItemDO::getDeleted, false));
            String userId = String.valueOf(SecurityFrameworkUtils.getLoginUserId());
            OrderConsignorDO orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsignorDO::getId).last("limit 1"));
            OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsigneeDO::getId).last("limit 1"));
            // 更新所属客户经理(业务员)
//            if (Objects.isNull(orderDO.getParentOrderId()) || orderDO.getParentOrderId() == 0 || orderDO.getSplitSeparateOrder()) {
//                // 拆单子订单不执行客户经理分配规则，以原单为主
//                if (Objects.nonNull(orderDO.getCustomerId()) && orderDO.getCustomerId() > 0) {
//                    addOrderCustomerService(orderDO, Objects.equals(orderConsignorDO.getCustomerId(), orderDO.getCustomerId()) ? 1 : 2);
//                }
//            }
            orderBusinessService.costCalculation(userId, orderDO, orderConsignorDO.getCustomerId(), Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerId(),
                    orderConsignorDO.getCustomerContactsId(), Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerContactsId(), orderItemDOList, 16);
        }
    }

    @Override
    public void finishOrderSortingReverseReviewUnlock(String containerNumber, Collection<Long> orderIds) {
        List<OrderDO> orderDOList = new ArrayList<>();
        if (StringUtils.isNotBlank(containerNumber)) {
            orderDOList = orderMapper.selectList(new LambdaQueryWrapper<OrderDO>().eq(OrderDO::getContainerNumber, containerNumber));
        } else {
            orderDOList = orderMapper.selectList(new LambdaQueryWrapper<OrderDO>().in(OrderDO::getOrderId, orderIds));
        }
        for (OrderDO orderDO : orderDOList) {
            List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderDO.getOrderId()).eq(OrderItemDO::getDeleted, false));
            String userId = String.valueOf(SecurityFrameworkUtils.getLoginUserId());
            OrderConsignorDO orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsignorDO::getId).last("limit 1"));
            OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsigneeDO::getId).last("limit 1"));
            // 更新所属客户经理(业务员)
//            if (Objects.isNull(orderDO.getParentOrderId()) || orderDO.getParentOrderId() == 0 || orderDO.getSplitSeparateOrder()) {
//                // 拆单子订单不执行客户经理分配规则，以原单为主
//                if (Objects.nonNull(orderDO.getCustomerId()) && orderDO.getCustomerId() > 0) {
//                    addOrderCustomerService(orderDO, Objects.equals(orderConsignorDO.getCustomerId(), orderDO.getCustomerId()) ? 1 : 2);
//                }
//            }
            orderBusinessService.costCalculation(userId, orderDO, orderConsignorDO.getCustomerId(), Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerId(),
                    orderConsignorDO.getCustomerContactsId(), Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerContactsId(), orderItemDOList, 17);
        }
    }

    @Override
    public void updateOrderPrice(List<String> orderNumbers, Boolean isResetPrice) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
//        List<ReceivableDO> receivableDOList = receivableService.list(new LambdaQueryWrapper<ReceivableDO>()
//                .eq(ReceivableDO::getTotalAmount, BigDecimal.ZERO)
//                .eq(ReceivableDO::getFeeSource, 1));
//        if (Objects.nonNull(receivableDOList) && CollectionUtil.isNotEmpty(receivableDOList)) {
//            orderNumbers = receivableDOList.stream().map(ReceivableDO::getOrderNo).distinct().collect(Collectors.toList());
        List<OrderDO> list = orderMapper.selectList(new LambdaQueryWrapper<OrderDO>()
                .in(CollectionUtil.isNotEmpty(orderNumbers), OrderDO::getOrderNo, orderNumbers)
//                        .isNotNull(OrderDO::getParentOrderId) // 子订单
//                        .ne(OrderDO::getParentOrderId, 0)
//                        .between(OrderDO::getCreateTime, "2023-01-25 00:00:00", "2023-02-14 00:00:00")
                .eq(OrderDO::getDeleted, 0).notIn(OrderDO::getStatus, 0, 88));
//        List<OrderDO> list = orderMapper.selectList(new LambdaQueryWrapper<OrderDO>()
//                        .and(we -> we.gt(OrderDO::getMinMeteringVolume, 0)
//                                .or().gt(OrderDO::getMinMeteringWeight, 0)
//                                .or().gt(OrderDO::getMinMeteringQuantity, 0))
//                .eq(OrderDO::getDeleted, 0).notIn(OrderDO::getStatus, 0,88));
        log.info(JSONObject.toJSONString(list));

        for (OrderDO orderDO : list) {
            OrderConsignorDO orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsignorDO::getId).last("limit 1"));
            OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsigneeDO::getId).last("limit 1"));
            List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderDO.getOrderId()));
            orderBusinessService.costCalculation(userId.toString(), orderDO, orderConsignorDO.getCustomerId(), Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerId(),
                    orderConsignorDO.getCustomerContactsId(), Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerContactsId(), orderItemDOList, isResetPrice ? 20 : 8);
            // TODO 此处是否需要更新操作日志
        }
//        }
    }

    @Override
    public void updateGuanlianOrderStatus(List<String> orderNumbers) {
        List<OrderDO> orderDOList = orderGuanlianService.guanlianOrderList(orderNumbers);
        if (CollectionUtil.isNotEmpty(orderDOList)) {
            for (OrderDO orderDO : orderDOList) {
                if ((!Objects.equals(orderDO.getStatus(), OrderStatusEnum.CANCEL.getValue()) && orderDO.getStatus() < OrderStatusEnum.IN_WAREHOUSE.getValue())
                        || orderDO.getAbnormalState() > 0
                        || orderDO.getAuditType() > 0) {
                    updateGuanlianOrderStatus(orderDO);
                }
            }
        }
    }


    @Override
    public long getUnWriteOffCount(Collection<Long> orderIds) {
        return receivableService.count(new LambdaQueryWrapper<ReceivableDO>()
                .in(ReceivableDO::getOrderId, orderIds)
                .ne(ReceivableDO::getState, 2)

        );
    }


    @Override
    public void airCan(Long orderId) {
        orderBusinessService.addOrderOperateLog(orderId, "确认可出", null);
        orderMapper.update(null, new LambdaUpdateWrapper<OrderDO>().set(OrderDO::getAirShipment, 2).eq(OrderDO::getOrderId, orderId));
    }

    @Override
    public void orderCouponUpdate(OrderDO orderDO, String msg) {
        List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderDO.getOrderId()).eq(OrderItemDO::getDeleted, false));
        String userId = String.valueOf(SecurityFrameworkUtils.getLoginUserId());
        OrderConsignorDO orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsignorDO::getId).last("limit 1"));
        OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsigneeDO::getId).last("limit 1"));
        orderBusinessService.costCalculation(userId, orderDO, orderConsignorDO.getCustomerId(), Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerId(),
                orderConsignorDO.getCustomerContactsId(), Objects.isNull(orderConsigneeDO) ? 0L : orderConsigneeDO.getCustomerContactsId(), orderItemDOList, 50);
        orderBusinessService.addOrderOperateLog(orderDO.getOrderId(), "有活动更新订单计价", null);
    }

    @Override
    public void airNotCan(Long orderId) {
        orderBusinessService.addOrderOperateLog(orderId, "确认不可出", null);
        orderMapper.update(null, new LambdaUpdateWrapper<OrderDO>().set(OrderDO::getAirShipment, 1).eq(OrderDO::getOrderId, orderId));
    }

    @Override
    public void updateSumDataPrevPacked(Long orderId) {
        orderMapper.updateSumDataPrevPacked(orderId);
    }

    @Override
    public Long getOrderIdByOrderNo(String orderNo) {
        return orderMapper.getOrderIdByOrderNo(orderNo);

    }

    /*
    更新订单业绩类型 yeji_type,yeji_create_date,cal_v_value

    yejiType 0是老客户业界，1 是新客户业绩
    */
    public void UpdateOrderYeJiType(Long orderId, int yejiType) {
        orderMapper.UpdateOrderYeJiType(orderId, yejiType);
    }

    /*
     更新订单V值
     yeji_create_date 业绩产生时间,方便报表统计
     */
    public void UpdateOrderVValue(Long orderId, BigDecimal calVvalue, Date
            yejiCreateDate) {
        orderMapper.UpdateOrderVValue(orderId, calVvalue, yejiCreateDate);
    }

    //修改订单的客户经理
    public void updateOrderSalesmanId(Long orderId, Long salesman_id) {
        orderMapper.updateOrderSalesmanId(orderId, salesman_id);
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateOrderCustomerAndSalesmanId(Long customerId, Long salesmanId, Long orderId) {
        orderMapper.updateOrderCustomerAndSalesmanId(customerId, salesmanId, orderId);
    }


    @Override
    public Long copyOrder(Long copyOrderId, MemberUserDO memberUserDO) {
        OrderDO orderDO = orderMapper.selectById(copyOrderId);
        if (Objects.isNull(orderDO)) {
            throw exception(ORDER_NOT_EXISTS);
        }
        // 重新生成订单编号, 并重置订单中其他冗余信息
        OrderDO newOrder = new OrderDO();
        BeanUtils.copyProperties(orderDO, newOrder);
        // 初始化订单信息
        initializeOrderInfo(newOrder);
        // 生成草稿订单编号
        String newOrderNo = "DRAFT-" + System.currentTimeMillis();
        newOrder.setOrderNo(newOrderNo);
        if (Objects.nonNull(memberUserDO)) {
            // 会员端下单，需要保存会员id信息
            newOrder.setUserId(memberUserDO.getId());
        } else {
            newOrder.setUserId(0L);
        }
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        String creator = String.valueOf(loginUser != null ? loginUser.getId() : null);
        Date now = new Date();

        newOrder.setCreator(creator);
        newOrder.setUpdater(creator);
        newOrder.setCreateTime(now);
        newOrder.setUpdateTime(now);

        orderMapper.insert(newOrder);

        Long newOrderId = newOrder.getOrderId();
        // 始发地
        OrderDepartureDO orderDepartureDO = orderDepartureService.getOne(new LambdaQueryWrapper<OrderDepartureDO>().eq(OrderDepartureDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderDepartureDO::getId).last("limit 1"));

        OrderDepartureDO departureDO = new OrderDepartureDO();
        BeanUtils.copyProperties(orderDepartureDO, departureDO);
        departureDO.setId(null);
        departureDO.setOrderId(newOrderId);
        departureDO.setCreator(creator);
        departureDO.setUpdater(creator);
        departureDO.setCreateTime(now);
        departureDO.setUpdateTime(now);
        orderDepartureService.save(departureDO);
        // 目的地
        OrderObjectiveDO orderObjectiveDO = orderObjectiveService.getOne(new LambdaQueryWrapper<OrderObjectiveDO>().eq(OrderObjectiveDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderObjectiveDO::getId).last("limit 1"));
        OrderObjectiveDO objectiveDO = new OrderObjectiveDO();
        BeanUtils.copyProperties(orderObjectiveDO, objectiveDO);
        objectiveDO.setId(null);
        objectiveDO.setOrderId(newOrderId);
        objectiveDO.setCreator(creator);
        objectiveDO.setUpdater(creator);
        objectiveDO.setCreateTime(now);
        objectiveDO.setUpdateTime(now);
        orderObjectiveService.save(objectiveDO);
        // 发货人信息
        OrderConsignorDO orderConsignorDO = orderConsignorService.getOne(new LambdaQueryWrapper<OrderConsignorDO>().eq(OrderConsignorDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsignorDO::getId).last("limit 1"));
        OrderConsignorDO consignorDO = new OrderConsignorDO();
        BeanUtils.copyProperties(orderConsignorDO, consignorDO);
        consignorDO.setId(null);
        consignorDO.setOrderId(newOrderId);
        if (Objects.nonNull(memberUserDO)) {
            consignorDO.setRelationId(memberUserDO.getId());
        }
        consignorDO.setCreator(creator);
        consignorDO.setUpdater(creator);
        consignorDO.setCreateTime(now);
        consignorDO.setUpdateTime(now);
        orderConsignorService.save(consignorDO);
        // 收货人信息
        OrderConsigneeDO orderConsigneeDO = orderConsigneeService.getOne(new LambdaQueryWrapper<OrderConsigneeDO>().eq(OrderConsigneeDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderConsigneeDO::getId).last("limit 1"));
        OrderConsigneeDO consigneeDO = null;
        if (Objects.nonNull(orderConsigneeDO)) {
            consigneeDO = new OrderConsigneeDO();
            BeanUtils.copyProperties(orderConsigneeDO, consigneeDO);
            consigneeDO.setId(null);
            consigneeDO.setOrderId(newOrderId);
            consigneeDO.setCreator(creator);
            consigneeDO.setUpdater(creator);
            consigneeDO.setCreateTime(now);
            consigneeDO.setUpdateTime(now);
            orderConsigneeService.save(consigneeDO);
            newOrder.setHasConsignee(true);
        } else {
            newOrder.setHasConsignee(false);
        }
        if (newOrder.getIsCargoControl()) {
            // 控货信息
            OrderCargoControlDO orderCargoControlDO = orderCargoControlMapper.selectOne(new LambdaQueryWrapper<OrderCargoControlDO>().eq(OrderCargoControlDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderCargoControlDO::getId).last("limit 1"));
            OrderCargoControlDO cargoControlDO = new OrderCargoControlDO();
            BeanUtils.copyProperties(orderCargoControlDO, cargoControlDO);
            cargoControlDO.setId(null);
            cargoControlDO.setOrderId(newOrderId);
            cargoControlDO.setCreator(creator);
            cargoControlDO.setUpdater(creator);
            cargoControlDO.setCreateTime(now);
            cargoControlDO.setUpdateTime(now);
            orderCargoControlMapper.insert(cargoControlDO);
        }
        // 当订单的包装类型不为空时，创建特需需要在订单业务执行完成后再进行，避免部分订单数据还未插入
        if (StringUtils.isNotBlank(newOrder.getPackageType())) {
            String[] packageTypes = newOrder.getPackageType().split(StrUtil.COMMA);
            List<OrderSpecialNeedCreateReqVO> createReqVOList = new ArrayList<>();
            for (String packageType : packageTypes) {
                OrderSpecialNeedCreateReqVO reqVO =
                        new OrderSpecialNeedCreateReqVO();
                reqVO.setOrderId(newOrderId);
                reqVO.setAdvanceType(packageType);
                reqVO.setTransFee(BigDecimal.ZERO);
                reqVO.setTransCurrency(1);
                reqVO.setTodoDetail(newOrder.getPackageRemarks());
                createReqVOList.add(reqVO);
            }
            orderSpecialNeedService.createOrderSpecialNeed(createReqVOList, Boolean.FALSE);
        }
        // 商品信息
        List<OrderItemDO> itemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderDO.getOrderId()).orderByDesc(OrderItemDO::getOrderItemId));
        List<OrderItemDO> newItemDOList = itemDOList.stream().map(io -> copyNewOrderItem(io, newOrderId, newOrderNo, newOrder, now, creator)).collect(Collectors.toList());
        // 插入订单商品项
        orderBusinessService.costCalculation(creator,
                newOrder, consignorDO.getCustomerId(),
                Objects.isNull(consigneeDO) ? 0L : consigneeDO.getCustomerId(),
                consignorDO.getCustomerContactsId(),
                Objects.isNull(consigneeDO) ? 0L : consigneeDO.getCustomerContactsId(),
                newItemDOList, 1);

        try {
            if (memberUserDO != null && Objects.nonNull(consigneeDO)) {
                // app-web添加的订单
                AdminClientCreateEvent adminClientCreateEvent =
                        new AdminClientCreateEvent();
                //下单用户
                adminClientCreateEvent.setUid(memberUserDO.getId());

                //收货人信息

                adminClientCreateEvent.setName(orderConsigneeDO.getName());
                adminClientCreateEvent.setCompany(orderConsigneeDO.getCompany());
                adminClientCreateEvent.setPhone(orderConsigneeDO.getPhone());
                adminClientCreateEvent.setEmail(orderConsigneeDO.getEmail());
                adminClientCreateEvent.setAddress(orderConsigneeDO.getAddress());
                adminClientCreateEvent.setDialCode(Integer.parseInt(orderConsigneeDO.getCountryCode()));
                adminClientCreateEvent.setMaitou(newOrder.getMarks());
                adminClientCreateEvent.setDefaultContact(true);
                indirectCustomerService.createIndirectCustomer(
                        adminClientCreateEvent);

            }
        } catch (Exception e) {
            log.error("");
        }


        //发货人的信用日志
        customerCreditLogService.sendPackageCreditLog(orderConsignorDO.getCustomerContactsId(), newOrderId, newOrderNo);

        // 创建订单操作日志
        orderBusinessService.addOrderOperateLog(newOrderId,
                "新建订单", null);

//        //在创建完订单号，计算订单业绩类型
//        CalculateOrderYeJiTypeEvent even = new CalculateOrderYeJiTypeEvent();
//        even.setOrderId(newOrderId);
//        applicationContext.publishEvent(even);

        return newOrderId;
    }

    @NotNull
    private static OrderItemDO copyNewOrderItem(OrderItemDO io, Long newOrderId, String newOrderNo, OrderDO newOrder, Date now, String creator) {
        OrderItemDO orderItemDO = new OrderItemDO();
        orderItemDO.setOrderId(newOrderId);
        orderItemDO.setOrderNo(newOrderNo);
        orderItemDO.setTransportId(newOrder.getTransportId());
        orderItemDO.setLineId(newOrder.getLineId());
        orderItemDO.setChannelId(newOrder.getChannelId());
        orderItemDO.setLink(io.getLink());
        orderItemDO.setProdId(io.getProdId());
        orderItemDO.setProdAttrIds(io.getProdAttrIds());
        orderItemDO.setProdTitleEn(io.getProdTitleEn());
        orderItemDO.setProdType(io.getProdType());
        orderItemDO.setProdTitleZh(io.getProdTitleZh());
        orderItemDO.setVolume(io.getVolume());
        orderItemDO.setWeight(io.getWeight());
        orderItemDO.setQuantity(io.getQuantity());
        orderItemDO.setNum(io.getQuantity());
        orderItemDO.setWorth(io.getWorth());
        orderItemDO.setBoxGauge(io.getBoxGauge());
        orderItemDO.setBrand(io.getBrand());
        orderItemDO.setBrandType(io.getBrandType());
        orderItemDO.setCreateTime(now);
        orderItemDO.setCreator(creator);
        return orderItemDO;
    }

    /**
     * 初始化订单信息
     *
     * @param newOrder 需要初始化的订单信息
     */
    private static void initializeOrderInfo(OrderDO newOrder) {
        newOrder.setOrderId(null);
        newOrder.setOrderNo(null);
        newOrder.setContainerNumber(null);
        newOrder.setTidanNo(null);
        newOrder.setParentOrderId(null);
        newOrder.setParentNumber(null);
        newOrder.setNumber(null);
        newOrder.setInitialParentOrderId(null);
        newOrder.setInitialParentOrderNo(null);
        newOrder.setNoChargeRecord(null);
        newOrder.setOldNumbers(null);

        newOrder.setUserId(0L);
        newOrder.setSumNum(null);
        newOrder.setSumQuantity(null);
        newOrder.setSumVolume(null);
        newOrder.setSumWeight(null);
        newOrder.setPickleType(null);
        newOrder.setPickRatio(null);
        newOrder.setPickNum(null);
        newOrder.setReleaseRatio(null);
        newOrder.setReleaseNum(null);
        newOrder.setCost(null);
        newOrder.setPackingListUrl(null);
        newOrder.setCommissionPayable(null);
        newOrder.setSpecialVWeight(null);
        newOrder.setHandlerChannelAttrException(null);
        newOrder.setWeightBeforePack(null);
        newOrder.setWeightAfterPack(null);
        newOrder.setStockOverWeightLimit(null);
        newOrder.setFirstStockedTime(null);
//        newOrder.setHasConsignee(null);
        newOrder.setIsLimitUpdateConsignee(null);
        newOrder.setLockConsigneeDay(null);
        newOrder.setLockConsigneeTime(null);
//        newOrder.setDisplayBillLadingPrice(null);
        // 状态重置
        newOrder.setStatus(DRAFT.getValue());// 默认草稿订单
        newOrder.setCargoControlStatus(null);
        newOrder.setAbnormalState(null);
        newOrder.setInWarehouseState(null);
        newOrder.setShipmentState(null);
        newOrder.setAuditType(null);
        newOrder.setAuditResult(null);
        newOrder.setAirShipment(null);
        newOrder.setSplitSeparateOrder(null);
        newOrder.setPickState(null);
        newOrder.setGuanLianOrderStatus(null);
        newOrder.setOldInWarehouseState(null);
        newOrder.setOldStatus(null);
        newOrder.setOldShipmentState(null);
        // 时间重置
        newOrder.setTakeTime(null);
        newOrder.setUnloadTime(null);
        newOrder.setRucangTime(null);
        newOrder.setLoadTime(null);
        newOrder.setPreLoadTime(null);
        newOrder.setDeliveryDate(null);
        newOrder.setDaogangTime(null);
        newOrder.setQingguanTime(null);
        newOrder.setSplitTime(null);
        newOrder.setIsException(null);
        newOrder.setExceptionReason(null);
        newOrder.setExternalWarehouseJson(null);
        newOrder.setHasExitAndEntry(null);
        newOrder.setHasSendRucangSms(null);
        newOrder.setHasSendWarehouseInNotice(null);
    }
}
