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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.codingapi.tx.annotation.TxTransaction;
import com.google.common.collect.Lists;
import com.prolog.common.util.ToolKits;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.RestrictionBuilder;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.product.core.framework.util.PlgFxUsrUtils;
import com.prolog.rdc.tms.app.constant.BussinessConstant;
import com.prolog.rdc.tms.app.constant.DataDictionaryConstant;
import com.prolog.rdc.tms.app.constant.SeriaNnumberConstant;
import com.prolog.rdc.tms.app.dao.mapper.TmsLoadingBillDetailMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsLoadingBillHeaderMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillDetailMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillHeaderMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillNodeTrackingMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillOperateLogMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillPackageMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillTransportLogMapper;
import com.prolog.rdc.tms.app.model.dto.business.PendingReceiptDTO;
import com.prolog.rdc.tms.app.model.dto.business.PendingReceiptItemDetailDTO;
import com.prolog.rdc.tms.app.model.dto.business.PendingReceiptPackageDetailDTO;
import com.prolog.rdc.tms.app.model.entity.ShipbillNodeTracking;
import com.prolog.rdc.tms.app.model.entity.TmsLoadingBillDetailModel;
import com.prolog.rdc.tms.app.model.entity.TmsLoadingBillHeaderModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillDetailModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillHeaderModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillOperateLogModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillPackageModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillTransLogModel;
import com.prolog.rdc.tms.app.model.vo.business.PendingReceiptConfirmVO;
import com.prolog.rdc.tms.app.model.vo.business.PendingReceiptQueryVO;
import com.prolog.rdc.tms.app.proxy.MainDataProxy;
import com.prolog.rdc.tms.app.service.business.PendingReceiptService;
import com.prolog.rdc.tms.app.service.business.ShipbillCommonService;
import com.prolog.rdc.tms.app.util.ConvertorUtil;
import com.prolog.rdc.tms.app.util.MessageUtil;
import com.prolog.rdc.tms.model.dto.message.SendMessageDTO;
import com.prolog.rdc.tms.model.entity.SysRefdatadModel;
import com.prolog.rdc.tms.model.enums.MessageOrderTypeEnum;
import com.prolog.rdc.tms.model.enums.MessageTypeEnum;
import com.prolog.rdc.tms.model.vo.basicConfigure.ApprovalOpenVO;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author hongbo.pan
 * @date 2023/1/16
 */
@Service
public class PendingReceiptServiceImpl implements PendingReceiptService {

    @Autowired
    private TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

    @Autowired
    private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

    @Autowired
    private TmsLoadingBillHeaderMapper tmsLoadingBillHeaderMapper;

    @Autowired
    private TmsShipbillTransportLogMapper tmsShipbillTransportLogMapper;

    @Autowired
    private TmsShipbillDetailMapper tmsShipbillDetailMapper;

    @Autowired
    private TmsShipbillPackageMapper tmsShipbillPackageMapper;

    @Autowired
    private ConvertorUtil convertorUtil;

    @Autowired
    private MaindataFeign maindataTmsResource;

    @Autowired
    private MainDataProxy mainDataProxy;

    @Autowired
    private TmsShipbillNodeTrackingMapper tmsShipbillNodeTrackingMapper;

    @Autowired
    private TmsShipbillOperateLogMapper tmsShipbillOperateLogMapper;

    @Autowired
    private ShipbillCommonService shipbillCommonService;

    /**
     * 回单查询
     * @param vo
     * @return
     */
    @Override
    public Page<PendingReceiptDTO> findByCondition(PendingReceiptQueryVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        ToolKits.isParamNull(user, "当前人员没有操作权限");
        vo = setDataPermission(vo);
        PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
        List<PendingReceiptDTO> pendingReceiptDTOList = tmsShipbillHeaderMapper.pendingReceiptQuery(vo);
        if (CollectionUtil.isNotEmpty(pendingReceiptDTOList)) {
            List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] {
                    DataDictionaryConstant.SHIPBILL_STATUS, // 运单状态
                    DataDictionaryConstant.TRANSPORT_STATUS, // 运输状态
                    DataDictionaryConstant.ABNORMAL_STATUS, // 异常状态
                    DataDictionaryConstant.SCAN_STATUS, // 扫描状态
                    DataDictionaryConstant.LINE_CARRIER_TYPE, // 承运方类型
                    DataDictionaryConstant.DELIVERY_METHOD_TYPE, // 配送方式
                    DataDictionaryConstant.TRANSPORT_TYPE, // 运输类型(运输模式)
                    DataDictionaryConstant.TEMPERATURE_REQUIREMENT, // 温度要求
                    DataDictionaryConstant.SHIPPER_TYPE, // 发货方类型
                    DataDictionaryConstant.CONSIGNEE_TYPE, // 收货方类型
                    DataDictionaryConstant.ORDER_TYPE, // 订单类型
                    DataDictionaryConstant.ORDER_BUSINESS_TYPE // 订单业务类型
            });
            pendingReceiptDTOList.forEach(dto -> {
                dto.setLoadingBillId(dto.getLoadingBillNo());
                dto.setPackageDetailDTOList(getPackageDetailDTO(dto.getShipbillId()));
                dto.setItemDetailDTOList(getItemDetailDTO(dto.getShipbillId()));
                dto.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SHIPBILL_STATUS, String.valueOf(dto.getStatus())));
                dto.setTransportStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TRANSPORT_STATUS, String.valueOf(dto.getTransportStatus())));
                dto.setAbnormalStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ABNORMAL_STATUS, String.valueOf(dto.getAbnormalStatus())));
                dto.setScanStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SCAN_STATUS, String.valueOf(dto.getScanStatus())));
                dto.setOrderTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_TYPE, String.valueOf(dto.getOrderType())));
                dto.setOrderBusinessTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_BUSINESS_TYPE, String.valueOf(dto.getOrderBusinessType())));
                dto.setDeliveryMethodTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.DELIVERY_METHOD_TYPE, String.valueOf(dto.getDeliveryMethodType())));
                dto.setTransportTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TRANSPORT_TYPE, String.valueOf(dto.getTransportType())));
                dto.setTemperatureRequirementName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TEMPERATURE_REQUIREMENT, String.valueOf(dto.getTemperatureRequirement())));
                dto.setShipperTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SHIPPER_TYPE, String.valueOf(dto.getShipperType())));
                dto.setConsigneeTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.CONSIGNEE_TYPE, String.valueOf(dto.getConsigneeType())));
                if (!DataDictionaryConstant.SHIPPER_TYPE_CK.equals(dto.getShipperType())) {
                    dto.setShipperName(dto.getShipperUnitName() + DataDictionaryConstant.Line_SYMBOL + dto.getShipperName());
                }
                if (!DataDictionaryConstant.CONSIGNEE_TYPE_CK.equals(dto.getConsigneeType())) {
                    dto.setConsigneeName(dto.getConsigneeUnitName() + DataDictionaryConstant.Line_SYMBOL + dto.getConsigneeName());
                }
            });
        }
        return PageUtils.getPage(pendingReceiptDTOList);
    }

    /**
     * 回单确认
     * @param vo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void confirm(PendingReceiptConfirmVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        ToolKits.isParamNull(user, "当前人员没有操作权限");
        ToolKits.isParamNull(vo.getReceiptPicUrl(), "请上传回单图片");
        List<String> shipbillIdList = vo.getShipbillIdList().stream().flatMap(s -> Arrays.stream(s.split(","))).collect(Collectors.toList());

        List<String> loadingDetailIds = Lists.newArrayList();
        shipbillIdList.forEach(shipbillId -> {
            TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(shipbillId, TmsShipbillHeaderModel.class);
            if (!DataDictionaryConstant.SHIPBILL_STATUS_HD_PIC.equals(tmsShipbillHeaderModel.getStatus())) {
                throw new BizException("运单【" + shipbillId + "】状态不为待回单");
            }
            Boolean isOpen = approvalOpen(tmsShipbillHeaderModel, DataDictionaryConstant.APPROVAL_FLOW_TYPE_START_RECEIPT, user);

            Integer status = DataDictionaryConstant.SHIPBILL_STATUS_END;
            if (isOpen) {
                status = DataDictionaryConstant.SHIPBILL_STATUS_HD_PIC_APPROVAL;
            } else {
                if (DataDictionaryConstant.WHETHER_YES.equals(tmsShipbillHeaderModel.getReturnOrderFlag())) {
                    status = DataDictionaryConstant.SHIPBILL_STATUS_HD_ZB;
                }
            }
            updateShipBillStatus(tmsShipbillHeaderModel, vo, isOpen, status);
            updateLoadingBillStatus(tmsShipbillHeaderModel, isOpen, status);
            // 运单同步BMS
            if (DataDictionaryConstant.SHIPBILL_STATUS_END.equals(status) &&
                    !DataDictionaryConstant.SHIPBILL_ABNORMAL_STATUS.equals(tmsShipbillHeaderModel.getAbnormalStatus())) {
                Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
                Restriction r1 = Restrictions.eq("shipbillId", tmsShipbillHeaderModel.getShipbillId());
                Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
                criteria.setRestriction(Restrictions.and(r1, r2));
                criteria.setOrder(Order.newInstance().desc(new String[] { "createtime" }));
                List<TmsLoadingBillDetailModel> loadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);
                if (ToolKits.isNotEmpty(loadingBillDetailModels)) {
                    TmsLoadingBillDetailModel tmsLoadingBillDetailModel = loadingBillDetailModels.get(0);
                    loadingDetailIds.add(tmsLoadingBillDetailModel.getId());
                }
            }
            MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.SHIP_NO.getCode(), MessageTypeEnum.RECEIPT.getCode(), Lists.newArrayList(shipbillId)));
        });

        // 运单同步BMS
        if (ToolKits.isNotEmpty(loadingDetailIds)) {
            shipbillCommonService.pushShipbillBmsData(loadingDetailIds);
        }
    }

    /**
     * 设置数据权限
     * @param vo
     * @return
     */
    private PendingReceiptQueryVO setDataPermission(PendingReceiptQueryVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        vo.setEnterpriseId(user.getEnterpriseId());
        vo.setUserType(user.getUserType());
        // 承运商
        if (BussinessConstant.USER_TYPE_CYS.equals(user.getUserType())){
            vo.setCarrierId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
        } else if (BussinessConstant.USER_TYPE_ZY.equals(user.getUserType())){
            vo.setDeptList(user.getDepts());
            // 部门权限
            if (BussinessConstant.USER_DEPARTMENT_AUTH_Y.equals(user.getOwnedAllDataAuthFlag())) {
                vo.setIsDept("YES");
            } else {
                vo.setIsDept("NO");
                // 货主
                vo.setConsignorList(user.getConsignors());
                // 客户
                vo.setCustomerList(user.getCustomers());
                // 供应商
                vo.setSupplierList(user.getSuppliers());
                // 仓库
                vo.setWarehouseList(user.getWarehouses());
            }
        } else if (BussinessConstant.USER_TYPE_SJ.equals(user.getUserType())){
            if (ObjectUtil.isNull(vo.getDriverId())) {
                throw new BizException("司机id不能为空");
            }
            if (ObjectUtil.isNull(vo.getVehiclePlateNumber())) {
                throw new BizException("车牌号不能为空");
            }
        }
        return vo;
    }

    /**
     * 获取包裹明细
     * @param shipBillId
     * @return
     */
    @Override
    public List<PendingReceiptPackageDetailDTO> getPackageDetailDTO(String shipBillId) {
        List<PendingReceiptPackageDetailDTO> result = Lists.newArrayList();
        Criteria ctr = Criteria.forClass(TmsShipbillPackageModel.class);
        Restriction rt1 = new RestrictionBuilder()
                .eq("shipbillId",shipBillId)
                .build();
        ctr.setRestriction(rt1);
        List<TmsShipbillPackageModel> packageList = tmsShipbillPackageMapper.findByCriteria(ctr);
        if (CollectionUtil.isNotEmpty(packageList)) {
            result = packageList.stream().map(packageModel -> {
                PendingReceiptPackageDetailDTO packageDetailDTO = new PendingReceiptPackageDetailDTO();
                BeanUtils.copyProperties(packageModel, packageDetailDTO);
                return packageDetailDTO;
            }).collect(Collectors.toList());
        }
        return result;
    }

    /**
     * 获取商品明细
     * @param shipBillId
     * @return
     */
    @Override
    public List<PendingReceiptItemDetailDTO> getItemDetailDTO(String shipBillId) {
        List<PendingReceiptItemDetailDTO> result = Lists.newArrayList();
        Criteria ctr = Criteria.forClass(TmsShipbillDetailModel.class);
        Restriction rt1 = new RestrictionBuilder()
                .eq("shipbillId",shipBillId)
                .build();
        ctr.setRestriction(rt1);
        List<TmsShipbillDetailModel> detailModelList = tmsShipbillDetailMapper.findByCriteria(ctr);
        if (CollectionUtil.isNotEmpty(detailModelList)) {
            result = detailModelList.stream().map(detailModel -> {
                PendingReceiptItemDetailDTO detailDTO = new PendingReceiptItemDetailDTO();
                BeanUtils.copyProperties(detailModel, detailDTO);
                return detailDTO;
            }).collect(Collectors.toList());
        }
        return result;
    }

    /**
     * 回单匹配审批流程
     * @param model
     * @param approvalFlowType
     * @param user
     * @return
     */
    private Boolean approvalOpen(TmsShipbillHeaderModel model, Integer approvalFlowType, UserEntity user) {
        ApprovalOpenVO approvalOpenVO = new ApprovalOpenVO();
        approvalOpenVO.setApprovalFlowType(approvalFlowType);
        approvalOpenVO.setApprovalObjectId(model.getShipbillId());
        approvalOpenVO.setApprovalObjectCode(model.getShipbillNo());
        approvalOpenVO.setApprovalObjectName(model.getShipbillNo());
        approvalOpenVO.setInitiatedUserId(user.getUserid());
        approvalOpenVO.setInitiatedUserName(user.getNickname());
        approvalOpenVO.setDeliveryMethodType(model.getDeliveryMethodType());
        approvalOpenVO.setShipperType(model.getShipperType());
        approvalOpenVO.setShipperUnitId(model.getShipperUnitId());
        approvalOpenVO.setConsigneeType(model.getConsigneeType());
        approvalOpenVO.setConsigneeUnitId(model.getConsigneeUnitId());
        approvalOpenVO.setOrderType(model.getOrderType());
        approvalOpenVO.setOrderBusinessType(model.getOrderBusinessType());
        approvalOpenVO.setTransportType(model.getTransportType());
        approvalOpenVO.setTemperatureRequirement(model.getTemperatureRequirement());
        approvalOpenVO.setCargoOwnerId(model.getCargoOwnerId());
        approvalOpenVO.setDepartmentId(model.getDepartmentId());
        RestMessage<Boolean> restMessage1 = maindataTmsResource.openExecute(approvalOpenVO);
        if (!restMessage1.isSuccess()) {
            throw new BizException("调用maindata服务是否开启审批流接口失败:" + restMessage1.getMessage());
        }
        return restMessage1.getData();
    }

    /**
     * 更新运单状态
     * @param tmsShipBillHeaderModel
     * @param vo
     * @param isOpen
     * @param newStatus
     */
    private void updateShipBillStatus(TmsShipbillHeaderModel tmsShipBillHeaderModel, PendingReceiptConfirmVO vo, Boolean isOpen, Integer newStatus) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        shipBillLog(vo, tmsShipBillHeaderModel.getShipbillId(), isOpen, tmsShipBillHeaderModel.getStatus(), newStatus);
        tmsShipBillHeaderModel.setStatus(newStatus);
        tmsShipBillHeaderModel.setUpdateperson(user.getNickname());
        tmsShipBillHeaderModel.setUpdatetime(new Date());
        tmsShipbillHeaderMapper.update(tmsShipBillHeaderModel);
        if (!isOpen) {
            // 递归更新父级运单签收状态
            String fatherShipBillId = tmsShipBillHeaderModel.getFatherShipbillId();
            while (StrUtil.isNotBlank(fatherShipBillId)) {
                TmsShipbillHeaderModel fatherShipBill = tmsShipbillHeaderMapper.findById(fatherShipBillId, TmsShipbillHeaderModel.class);
                if (ObjectUtil.isNotNull(fatherShipBill)) {
                    List<TmsShipbillHeaderModel> childShipBillList = getChildTmsShipBillHeaderModel(fatherShipBillId);
                    if (childShipBillList.stream().allMatch(childShipBill -> newStatus.equals(childShipBill.getStatus()))) {
                        shipBillLog(vo, fatherShipBill.getShipbillId(), false, fatherShipBill.getStatus(), newStatus);
                        fatherShipBill.setStatus(newStatus);
                        fatherShipBill.setUpdateperson(user.getNickname());
                        fatherShipBill.setUpdatetime(new Date());
                        tmsShipbillHeaderMapper.update(fatherShipBill);
                    }
                    fatherShipBillId = fatherShipBill.getFatherShipbillId();
                } else {
                    fatherShipBillId = StrUtil.EMPTY;
                }
            }
        }
    }

    /**
     * 更新派车单签收状态
     * @param tmsShipBillHeaderModel
     * @param isOpen
     * @param newStatus
     */
    private void updateLoadingBillStatus(TmsShipbillHeaderModel tmsShipBillHeaderModel, Boolean isOpen, Integer newStatus) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        if (isOpen) {
            Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
            Restriction r1 = Restrictions.eq("shipbillId", tmsShipBillHeaderModel.getShipbillId());
            Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
            criteria.setRestriction(Restrictions.and(r1, r2));
            criteria.setOrder(Order.newInstance().desc(new String[] { "createtime" }));
            List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
            TmsLoadingBillDetailModel tmsLoadingBillDetailModel = tmsLoadingBillDetailModelList.get(0);
            tmsLoadingBillDetailModel.setUpdatetime(new Date());
            tmsLoadingBillDetailModel.setUpdateperson(user.getNickname());
            tmsLoadingBillDetailModel.setStatus(newStatus);
            tmsLoadingBillDetailMapper.update(tmsLoadingBillDetailModel);
            return;
        }
        List<TmsShipbillHeaderModel> allRelationShipBill = Lists.newArrayList(tmsShipBillHeaderModel);
        String fatherShipBillId = tmsShipBillHeaderModel.getFatherShipbillId();
        while (StrUtil.isNotBlank(fatherShipBillId)) {
            TmsShipbillHeaderModel fatherShipBill = tmsShipbillHeaderMapper.findById(fatherShipBillId, TmsShipbillHeaderModel.class);
            if (ObjectUtil.isNotNull(fatherShipBill)) {
                allRelationShipBill.add(fatherShipBill);
                fatherShipBillId = fatherShipBill.getFatherShipbillId();
            } else {
                fatherShipBillId = StrUtil.EMPTY;
            }
        }
        Map<String, TmsShipbillHeaderModel> allRelationShipBillIdMap = allRelationShipBill.stream().collect(Collectors.toMap(t1 -> t1.getShipbillId(), t2 -> t2, (t1, t2) -> t2));
        Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
        Restriction restriction = new RestrictionBuilder().in("shipbillId", allRelationShipBillIdMap.keySet().toArray()).build();
        criteria.setRestriction(restriction);
        List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
        tmsLoadingBillDetailModelList.forEach(tmsLoadingBillDetailModel -> {
            TmsShipbillHeaderModel tmsShipbillHeaderModel = allRelationShipBillIdMap.get(tmsLoadingBillDetailModel.getShipbillId());
            if (ObjectUtil.isNotNull(tmsShipbillHeaderModel)) {
                tmsLoadingBillDetailModel.setStatus(newStatus);
                tmsLoadingBillDetailModel.setUpdateperson(user.getNickname());
                tmsLoadingBillDetailModel.setUpdatetime(new Date());
                tmsLoadingBillDetailMapper.update(tmsLoadingBillDetailModel);
            }
        });
        List<String> loadingBillIdList = tmsLoadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getLoadingBillId).distinct().collect(Collectors.toList());
        criteria = Criteria.forClass(TmsLoadingBillHeaderModel.class);
        restriction = new RestrictionBuilder().in("loadingBillId", loadingBillIdList.toArray()).build();
        criteria.setRestriction(restriction);
        List<TmsLoadingBillHeaderModel> tmsLoadingBillHeaderModelList = tmsLoadingBillHeaderMapper.findByCriteria(criteria);
        tmsLoadingBillHeaderModelList.forEach(tmsLoadingBillHeaderModel -> {
            Criteria detailCriteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
            Restriction detailRestriction = new RestrictionBuilder().eq("loadingBillId", tmsLoadingBillHeaderModel.getLoadingBillId()).build();
            detailCriteria.setRestriction(detailRestriction);
            List<TmsLoadingBillDetailModel> detailModelList = tmsLoadingBillDetailMapper.findByCriteria(detailCriteria);
            if (detailModelList.stream().allMatch(detailModel -> newStatus.equals(detailModel.getStatus()))) {
                tmsLoadingBillHeaderModel.setStatus(newStatus);
                tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
                tmsLoadingBillHeaderModel.setUpdatetime(new Date());
                tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);
            }
        });
    }

    /**
     * 记录运单日志
     * @param vo
     * @param shipBillId
     * @param isOpen
     * @param oldStatus
     * @param newStatus
     */
    private void shipBillLog(PendingReceiptConfirmVO vo, String shipBillId, Boolean isOpen, Integer oldStatus, Integer newStatus) {
        String event = isOpen ? DataDictionaryConstant.SHIPBILL_STATUSNAME_HD_PIC_APPROVAL : DataDictionaryConstant.SHIPBILL_STATUSNAME_HD_PIC;

        UserEntity user = PlgFxUsrUtils.getUserEntity();
        ShipbillNodeTracking shipbillNodeTracking = new ShipbillNodeTracking();
        shipbillNodeTracking.setStatus(newStatus);
        shipbillNodeTracking.setNodeEvent(event);
        String id = mainDataProxy.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_NODE_TRACKING_ID);
        shipbillNodeTracking.setId(id);
        shipbillNodeTracking.setShipbillId(shipBillId);
        shipbillNodeTracking.setShipbillNo(shipBillId);
        shipbillNodeTracking.setNodeDate(new Date());
        shipbillNodeTracking.setUserId(user.getUserid());
        shipbillNodeTracking.setUserName(user.getNickname());
        shipbillNodeTracking.setEnterpriseId(user.getEnterpriseId());
        shipbillNodeTracking.setEnterpriseName(user.getEnterpriseName());
        shipbillNodeTracking.setCreateperson(user.getNickname());
        shipbillNodeTracking.setCreatetime(new Date());
        shipbillNodeTracking.setUpdateperson(user.getNickname());
        shipbillNodeTracking.setUpdatetime(new Date());
        shipbillNodeTracking.setPicUrl(vo.getReceiptPicUrl());
        tmsShipbillNodeTrackingMapper.save(shipbillNodeTracking);

        TmsShipbillOperateLogModel tmsShipbillOperateLogModel = new TmsShipbillOperateLogModel();
        tmsShipbillOperateLogModel.setOperateEvent(event);
        tmsShipbillOperateLogModel.setOldStatus(oldStatus);
        tmsShipbillOperateLogModel.setNewStatus(newStatus);
        String operateId = mainDataProxy.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_OPERATE_LOG_ID);
        tmsShipbillOperateLogModel.setId(operateId);
        tmsShipbillOperateLogModel.setShipbillId(shipBillId);
        tmsShipbillOperateLogModel.setShipbillNo(shipBillId);
        tmsShipbillOperateLogModel.setOperateDate(new Date());
        tmsShipbillOperateLogModel.setUserId(user.getUserid());
        tmsShipbillOperateLogModel.setUserName(user.getNickname());
        tmsShipbillOperateLogModel.setEnterpriseId(user.getEnterpriseId());
        tmsShipbillOperateLogModel.setEnterpriseName(user.getEnterpriseName());
        tmsShipbillOperateLogModel.setCreateperson(user.getNickname());
        tmsShipbillOperateLogModel.setCreatetime(new Date());
        tmsShipbillOperateLogModel.setUpdateperson(user.getNickname());
        tmsShipbillOperateLogModel.setUpdatetime(new Date());
        tmsShipbillOperateLogMapper.save(tmsShipbillOperateLogModel);

        Criteria criteria = Criteria.forClass(TmsShipbillTransLogModel.class);
        Restriction r1 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, shipBillId);
        criteria.setRestriction(Restrictions.and(r1));
        List<TmsShipbillTransLogModel> logModelList = tmsShipbillTransportLogMapper.findByCriteria(criteria);
        TmsShipbillTransLogModel dbLogModel = logModelList.get(0);
        dbLogModel.setUpdatetime(new Date());
        dbLogModel.setUpdateperson(user.getNickname());
        dbLogModel.setReceiptTime(new Date());
        dbLogModel.setReceiptMemo(vo.getMemo());
        tmsShipbillTransportLogMapper.update(dbLogModel);
    }

    /**
     * 通过父级运单找子单
     * @param shipBillId
     * @return
     */
    private List<TmsShipbillHeaderModel> getChildTmsShipBillHeaderModel(String shipBillId) {
        Criteria criteria = Criteria.forClass(TmsShipbillHeaderModel.class);
        Restriction restriction = new RestrictionBuilder().eq("fatherShipbillId", shipBillId).build();
        criteria.setRestriction(restriction);
        return tmsShipbillHeaderMapper.findByCriteria(criteria);
    }
}
