package cn.iocoder.foodnexus.module.erp.service.purchase;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.foodnexus.framework.common.enums.CheckTaskStatus;
import cn.iocoder.foodnexus.framework.common.pojo.PageResult;
import cn.iocoder.foodnexus.framework.common.util.CommonUtil;
import cn.iocoder.foodnexus.framework.common.util.object.BeanUtils;
import cn.iocoder.foodnexus.framework.common.util.spring.SpringUtils;
import cn.iocoder.foodnexus.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.foodnexus.module.erp.api.PurchaseOrderSplitEvent;
import cn.iocoder.foodnexus.module.erp.api.enums.ErpDeliveryStatus;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInSaveReqVO;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderPageReqVO;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderSaveReqVO;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.supplier.SupplierPurchaseOrderDeliveryReqVO;
import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO;
import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO;
import cn.iocoder.foodnexus.module.erp.dal.mysql.purchase.ErpPurchaseOrderItemMapper;
import cn.iocoder.foodnexus.module.erp.dal.mysql.purchase.ErpPurchaseOrderMapper;
import cn.iocoder.foodnexus.module.erp.dal.redis.no.ErpNoRedisDAO;
import cn.iocoder.foodnexus.module.erp.api.enums.ErpAuditStatus;
import cn.iocoder.foodnexus.module.erp.service.finance.ErpAccountService;
import cn.iocoder.foodnexus.module.order.api.CheckTaskApi;
import cn.iocoder.foodnexus.module.order.api.CustomerOrderApi;
import cn.iocoder.foodnexus.module.order.api.CustomerOrderRecordApi;
import cn.iocoder.foodnexus.module.order.api.DeliveryStaffApi;
import cn.iocoder.foodnexus.module.order.dto.CustomerOrderDTO;
import cn.iocoder.foodnexus.module.order.dto.CustomerOrderItemDTO;
import cn.iocoder.foodnexus.module.order.dto.CustomerOrderRecordEvent;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.SupplierMonthOrderPageReqVO;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.SupplierMonthOrderRespVO;
import cn.iocoder.foodnexus.module.order.enums.CustomerOrderStatus;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

import static cn.iocoder.foodnexus.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.foodnexus.framework.common.util.collection.CollectionUtils.*;
import static cn.iocoder.foodnexus.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.foodnexus.module.erp.enums.ErrorCodeConstants.*;

// TODO 芋艿：记录操作日志

/**
 * ERP 采购订单 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
@Slf4j
public class ErpPurchaseOrderServiceImpl implements ErpPurchaseOrderService {

    @Resource
    private ErpPurchaseOrderMapper purchaseOrderMapper;
    @Resource
    private ErpPurchaseOrderItemMapper purchaseOrderItemMapper;

    @Autowired
    private ErpPurchaseInService purchaseInService;

    @Autowired
    private CheckTaskApi checkTaskApi;

    @Resource
    private ErpNoRedisDAO noRedisDAO;

    @Resource
    private ErpSupplierService supplierService;
    @Resource
    private ErpAccountService accountService;

    @Autowired
    private CustomerOrderApi customerOrderApi;

    @Autowired
    private CustomerOrderRecordApi orderRecordApi;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createPurchaseOrder(ErpPurchaseOrderSaveReqVO createReqVO) {
        // 1.1 校验订单项的有效性
        List<ErpPurchaseOrderItemDO> purchaseOrderItems = validatePurchaseOrderItems(createReqVO.getItems());
        // 1.2 校验供应商
        supplierService.validateSupplier(createReqVO.getSupplierId());
        // 1.3 校验结算账户
        if (createReqVO.getAccountId() != null) {
            accountService.validateAccount(createReqVO.getAccountId());
        }
        // 1.4 生成订单号，并校验唯一性
        String no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_ORDER_NO_PREFIX);
        if (purchaseOrderMapper.selectByNo(no) != null) {
            throw exception(PURCHASE_ORDER_NO_EXISTS);
        }

        // 2.1 插入订单
        ErpPurchaseOrderDO purchaseOrder = BeanUtils.toBean(createReqVO, ErpPurchaseOrderDO.class, in -> in
                .setNo(no).setStatus(ErpAuditStatus.APPROVE.getStatus()));
        calculateTotalPrice(purchaseOrder, purchaseOrderItems);
        purchaseOrderMapper.insert(purchaseOrder);
        // 2.2 插入订单项
        purchaseOrderItems.forEach(o -> o.setOrderId(purchaseOrder.getId()));
        purchaseOrderItemMapper.insertBatch(purchaseOrderItems);
        return purchaseOrder.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePurchaseOrder(ErpPurchaseOrderSaveReqVO updateReqVO) {
        // 1.1 校验存在
        ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrderExists(updateReqVO.getId());
        if (ErpAuditStatus.APPROVE.getStatus().equals(purchaseOrder.getStatus())) {
            throw exception(PURCHASE_ORDER_UPDATE_FAIL_APPROVE, purchaseOrder.getNo());
        }
        // 1.2 校验供应商
        supplierService.validateSupplier(updateReqVO.getSupplierId());
        // 1.3 校验结算账户
        if (updateReqVO.getAccountId() != null) {
            accountService.validateAccount(updateReqVO.getAccountId());
        }
        // 1.4 校验订单项的有效性
        List<ErpPurchaseOrderItemDO> purchaseOrderItems = validatePurchaseOrderItems(updateReqVO.getItems());

        // 2.1 更新订单
        ErpPurchaseOrderDO updateObj = BeanUtils.toBean(updateReqVO, ErpPurchaseOrderDO.class);
        calculateTotalPrice(updateObj, purchaseOrderItems);
        purchaseOrderMapper.updateById(updateObj);
        // 2.2 更新订单项
        updatePurchaseOrderItemList(updateReqVO.getId(), purchaseOrderItems);
    }

    private void calculateTotalPrice(ErpPurchaseOrderDO purchaseOrder, List<ErpPurchaseOrderItemDO> purchaseOrderItems) {
        purchaseOrder.setTotalCount(getSumValue(purchaseOrderItems, ErpPurchaseOrderItemDO::getCount, Integer::sum));
        purchaseOrder.setTotalProductPrice(getSumValue(purchaseOrderItems, ErpPurchaseOrderItemDO::getTotalPrice, Integer::sum, 0));
        purchaseOrder.setTotalTaxPrice(getSumValue(purchaseOrderItems, ErpPurchaseOrderItemDO::getTaxPrice, Integer::sum, 0));
        purchaseOrder.setTotalPrice(purchaseOrder.getTotalProductPrice() + (purchaseOrder.getTotalTaxPrice()));
        // 计算优惠价格
        if (purchaseOrder.getDiscountPercent() == null) {
            purchaseOrder.setDiscountPercent(0);
        }
        // purchaseOrder.setDiscountPrice(MoneyUtils.priceMultiplyPercent(purchaseOrder.getTotalPrice(), purchaseOrder.getDiscountPercent()));
        // purchaseOrder.setTotalPrice(purchaseOrder.getTotalPrice()/*.subtract(purchaseOrder.getDiscountPrice())*/);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePurchaseOrderStatus(Long id, Integer status) {
        boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status);
        // 1.1 校验存在
        ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrderExists(id);
        // 1.2 校验状态
        if (purchaseOrder.getStatus().equals(status)) {
            throw exception(approve ? PURCHASE_ORDER_APPROVE_FAIL : PURCHASE_ORDER_PROCESS_FAIL);
        }
        // 1.3 存在采购入单，无法反审核
        if (!approve && purchaseOrder.getInCount().compareTo(BigDecimal.ZERO) > 0) {
            throw exception(PURCHASE_ORDER_PROCESS_FAIL_EXISTS_IN);
        }
        // 1.4 存在采购退货单，无法反审核
        if (!approve && purchaseOrder.getReturnCount().compareTo(BigDecimal.ZERO) > 0) {
            throw exception(PURCHASE_ORDER_PROCESS_FAIL_EXISTS_RETURN);
        }

        // 2. 更新状态
        int updateCount = purchaseOrderMapper.updateByIdAndStatus(id, purchaseOrder.getStatus(),
                new ErpPurchaseOrderDO().setStatus(status));
        if (updateCount == 0) {
            throw exception(approve ? PURCHASE_ORDER_APPROVE_FAIL : PURCHASE_ORDER_PROCESS_FAIL);
        }
    }

    private List<ErpPurchaseOrderItemDO> validatePurchaseOrderItems(List<ErpPurchaseOrderSaveReqVO.Item> list) {
        // 1. 校验产品存在
        /*List<ErpProductDO> productList = productService.validProductList(
                convertSet(list, ErpPurchaseOrderSaveReqVO.Item::getProductId));
        Map<Long, ErpProductDO> productMap = convertMap(productList, ErpProductDO::getId);*/
        // 2. 转化为 ErpPurchaseOrderItemDO 列表
        return convertList(list, o -> BeanUtils.toBean(o, ErpPurchaseOrderItemDO.class, item -> {
            item.setTotalPrice((item.getProductPrice() * item.getCount()));
            if (item.getTotalPrice() == null) {
                return;
            }
            if (item.getTaxPercent() != null) {
                // item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent()));
            }
        }));
    }

    private void updatePurchaseOrderItemList(Long id, List<ErpPurchaseOrderItemDO> newList) {
        // 第一步，对比新老数据，获得添加、修改、删除的列表
        List<ErpPurchaseOrderItemDO> oldList = purchaseOrderItemMapper.selectListByOrderId(id);
        List<List<ErpPurchaseOrderItemDO>> diffList = diffList(oldList, newList, // id 不同，就认为是不同的记录
                (oldVal, newVal) -> oldVal.getId().equals(newVal.getId()));

        // 第二步，批量添加、修改、删除
        if (CollUtil.isNotEmpty(diffList.get(0))) {
            diffList.get(0).forEach(o -> o.setOrderId(id));
            purchaseOrderItemMapper.insertBatch(diffList.get(0));
        }
        if (CollUtil.isNotEmpty(diffList.get(1))) {
            purchaseOrderItemMapper.updateBatch(diffList.get(1));
        }
        if (CollUtil.isNotEmpty(diffList.get(2))) {
            purchaseOrderItemMapper.deleteByIds(convertList(diffList.get(2), ErpPurchaseOrderItemDO::getId));
        }
    }

    @Override
    public void updatePurchaseOrderInCount(Long id, Map<Long, BigDecimal> inCountMap) {
        List<ErpPurchaseOrderItemDO> orderItems = purchaseOrderItemMapper.selectListByOrderId(id);
        // 1. 更新每个采购订单项
        orderItems.forEach(item -> {
            BigDecimal inCount = inCountMap.getOrDefault(item.getId(), BigDecimal.ZERO);
            if (item.getInCount().equals(inCount)) {
                return;
            }
            /*if (inCount.compareTo(BigDecimal.valueOf(item.getCount())) > 0) {
                throw exception(PURCHASE_ORDER_ITEM_IN_FAIL_PRODUCT_EXCEED,
                        productService.getProduct(item.getProductId()).getName(), item.getCount());
            }*/
            purchaseOrderItemMapper.updateById(new ErpPurchaseOrderItemDO().setId(item.getId()).setInCount(inCount));
        });
        // 2. 更新采购订单
        BigDecimal totalInCount = getSumValue(inCountMap.values(), value -> value, BigDecimal::add, BigDecimal.ZERO);
        purchaseOrderMapper.updateById(new ErpPurchaseOrderDO().setId(id).setInCount(totalInCount));
    }

    @Override
    public void updatePurchaseOrderReturnCount(Long orderId, Map<Long, BigDecimal> returnCountMap) {
        List<ErpPurchaseOrderItemDO> orderItems = purchaseOrderItemMapper.selectListByOrderId(orderId);
        // 1. 更新每个采购订单项
        orderItems.forEach(item -> {
            BigDecimal returnCount = returnCountMap.getOrDefault(item.getId(), BigDecimal.ZERO);
            if (item.getReturnCount().equals(returnCount)) {
                return;
            }
            /*if (returnCount.compareTo(item.getInCount()) > 0) {
                throw exception(PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED,
                        productService.getProduct(item.getProductId()).getName(), item.getInCount());
            }*/
            purchaseOrderItemMapper.updateById(new ErpPurchaseOrderItemDO().setId(item.getId()).setReturnCount(returnCount));
        });
        // 2. 更新采购订单
        BigDecimal totalReturnCount = getSumValue(returnCountMap.values(), value -> value, BigDecimal::add, BigDecimal.ZERO);
        purchaseOrderMapper.updateById(new ErpPurchaseOrderDO().setId(orderId).setReturnCount(totalReturnCount));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePurchaseOrder(List<Long> ids) {
        // 1. 校验不处于已审批
        List<ErpPurchaseOrderDO> purchaseOrders = purchaseOrderMapper.selectByIds(ids);
        if (CollUtil.isEmpty(purchaseOrders)) {
            return;
        }
        purchaseOrders.forEach(purchaseOrder -> {
            if (ErpAuditStatus.APPROVE.getStatus().equals(purchaseOrder.getStatus())) {
                throw exception(PURCHASE_ORDER_DELETE_FAIL_APPROVE, purchaseOrder.getNo());
            }
        });

        // 2. 遍历删除，并记录操作日志
        purchaseOrders.forEach(purchaseOrder -> {
            // 2.1 删除订单
            purchaseOrderMapper.deleteById(purchaseOrder.getId());
            // 2.2 删除订单项
            purchaseOrderItemMapper.deleteByOrderId(purchaseOrder.getId());
        });
    }

    private ErpPurchaseOrderDO validatePurchaseOrderExists(Long id) {
        ErpPurchaseOrderDO purchaseOrder = purchaseOrderMapper.selectById(id);
        if (purchaseOrder == null) {
            throw exception(PURCHASE_ORDER_NOT_EXISTS);
        }
        return purchaseOrder;
    }

    @Override
    public ErpPurchaseOrderDO getPurchaseOrder(Long id) {
        return purchaseOrderMapper.selectById(id);
    }

    @Override
    public ErpPurchaseOrderDO validatePurchaseOrder(Long id) {
        ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrderExists(id);
        if (ObjectUtil.notEqual(purchaseOrder.getStatus(), ErpAuditStatus.APPROVE.getStatus())) {
            throw exception(PURCHASE_ORDER_NOT_APPROVE);
        }
        return purchaseOrder;
    }

    @Override
    public PageResult<ErpPurchaseOrderDO> getPurchaseOrderPage(ErpPurchaseOrderPageReqVO pageReqVO) {
        return purchaseOrderMapper.selectPage(pageReqVO);
    }

    // ==================== 订单项 ====================

    @Override
    public List<ErpPurchaseOrderItemDO> getPurchaseOrderItemListByOrderId(Long orderId) {
        return purchaseOrderItemMapper.selectListByOrderId(orderId);
    }

    @Override
    public List<ErpPurchaseOrderItemDO> getPurchaseOrderItemListByOrderIds(Collection<Long> orderIds) {
        if (CollUtil.isEmpty(orderIds)) {
            return Collections.emptyList();
        }
        return purchaseOrderItemMapper.selectListByOrderIds(orderIds);
    }

    /**
     * 发货/接单
     *
     * @param supplierId
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void delivery(SupplierPurchaseOrderDeliveryReqVO reqVO, Long supplierId, ErpDeliveryStatus oriStatus, ErpDeliveryStatus updateStatus, CustomerOrderStatus updateOrderStatus) {
        Map<Long, List<SupplierPurchaseOrderDeliveryReqVO.ProductFile>> idMap = CommonUtil.listConvertMap(reqVO.getIds(), SupplierPurchaseOrderDeliveryReqVO.Item::getId, SupplierPurchaseOrderDeliveryReqVO.Item::getProductFiles);
        Set<Long> ids = CommonUtil.listConvertSet(reqVO.getIds(), SupplierPurchaseOrderDeliveryReqVO.Item::getId);
        List<ErpPurchaseOrderDO> orderList = purchaseOrderMapper.selectList(Wrappers.<ErpPurchaseOrderDO>lambdaQuery()
                .in(ErpPurchaseOrderDO::getId, ids)
                .eq(CommonUtil.isNotEmpty(supplierId) ,ErpPurchaseOrderDO::getSupplierId, supplierId));

        if (CommonUtil.isEmpty(orderList)) {
            throw exception(PURCHASE_ORDER_NOT_EXISTS);
        }
        if (CommonUtil.isEmpty(supplierId)) {
            supplierId = orderList.get(0).getSupplierId();
        }

        Set<Long> customerOrderSet = new HashSet<>();
        for (ErpPurchaseOrderDO item : orderList) {
            if (!oriStatus.getStatus().equals(item.getDeliveryStatus())) {
                throw exception(PURCHASE_DELIVERY_STATUS_ERROR);
            }

            boolean isReCheck = CheckTaskStatus.ABNORMAL.getKey().equals(item.getCheckTaskStatus());

            CustomerOrderDTO customerOrder = customerOrderApi.queryById(item.getCustomerOrderId());
            if (CommonUtil.isEmpty(customerOrder)) {
                throw exception("订单不存在");
            }

            if (!customerOrderSet.contains(item.getCustomerOrderId()) && !isReCheck) {
                // 添加订单进度记录
                CustomerOrderRecordEvent event = new CustomerOrderRecordEvent();
                event.setOrderStatus(updateOrderStatus);
                event.setCustomerOrderId(item.getCustomerOrderId());
                event.setSupplierId(supplierId);
                event.setCopyWriter(CommonUtil.asList(supplierService.getSupplier(supplierId).getName()));
                orderRecordApi.recordEvent(event);
                customerOrderSet.add(item.getCustomerOrderId());
            }

            purchaseOrderMapper.update(Wrappers.<ErpPurchaseOrderDO>lambdaUpdate()
                    .set(ErpPurchaseOrderDO::getDeliveryStatus, updateStatus)
                    .eq(ErpPurchaseOrderDO::getId, item.getId()));

            List<SupplierPurchaseOrderDeliveryReqVO.ProductFile> productFiles = idMap.get(item.getId());
            if (CommonUtil.isNotEmpty(productFiles)) {
                productFiles.forEach(purchaseOrderItem -> {
                    purchaseOrderItemMapper.update(Wrappers.<ErpPurchaseOrderItemDO>lambdaUpdate()
                            .set(ErpPurchaseOrderItemDO::getAnnex, purchaseOrderItem.getAnnex())
                            .eq(ErpPurchaseOrderItemDO::getOrderId, item.getId())
                            .eq(ErpPurchaseOrderItemDO::getProductId, purchaseOrderItem.getProductId()));
                    customerOrderApi.updatePurchaseAnnex(item.getCustomerOrderId(), item.getSupplierId(), purchaseOrderItem.getProductId(), purchaseOrderItem.getAnnex());
                });
            }
        }


        if (updateStatus.equals(ErpDeliveryStatus.ARRIVAL)) {
            orderList.forEach(purchaseOrder -> {
                if (!Objects.equals(purchaseOrder.getCheckTaskStatus(), CheckTaskStatus.ABNORMAL.getKey())) {
                    // 新增采购入库单
                    ErpPurchaseInSaveReqVO inSaveReqVO = new ErpPurchaseInSaveReqVO();
                    inSaveReqVO.setInTime(LocalDateTime.now());
                    inSaveReqVO.setOrderId(purchaseOrder.getId());
                    inSaveReqVO.setFileUrl(purchaseOrder.getFileUrl());
                    inSaveReqVO.setRemark(purchaseOrder.getRemark());
                    List<ErpPurchaseOrderItemDO> purchaseOrderItems = purchaseOrderItemMapper.selectListByOrderId(purchaseOrder.getId());
                    inSaveReqVO.setItems(CommonUtil.listConvert(purchaseOrderItems, purchaseOrderItem ->
                            getItem(purchaseOrderItem, customerOrderApi.queryById(purchaseOrder.getCustomerOrderId()))));
                    purchaseInService.createPurchaseIn(inSaveReqVO);

                    // 新增来料质检
                    checkTaskApi.createByPurchaseOrderId(purchaseOrder.getId());
                }
            });
        }
    }

    private static ErpPurchaseInSaveReqVO.Item getItem(ErpPurchaseOrderItemDO purchaseOrderItemDO, CustomerOrderDTO customerOrder) {
        ErpPurchaseInSaveReqVO.Item item = new ErpPurchaseInSaveReqVO.Item();
        item.setOrderItemId(purchaseOrderItemDO.getId());
        item.setWarehouseId(customerOrder.getWarehouseAreaId());
        item.setProductId(purchaseOrderItemDO.getProductId());
        item.setProductUnit(purchaseOrderItemDO.getProductUnit());
        item.setProductPrice(purchaseOrderItemDO.getProductPrice());
        item.setCount(purchaseOrderItemDO.getCount());
        item.setTaxPercent(purchaseOrderItemDO.getTaxPercent());
        item.setRemark(purchaseOrderItemDO.getRemark());
        return item;
    }

    @Override
    public Map<String, Long> queryCountByDeliveryStatus(ErpPurchaseOrderPageReqVO pageReqVO) {
        Map<String, Long> resultMap = new HashMap<>();
        pageReqVO.setPageSize(-1);
        Long all = purchaseOrderMapper.selectCount(pageReqVO);
        resultMap.put("all", CommonUtil.getEls(all, 0L));
        if (CommonUtil.isNotEmpty(all) && all > 0) {
            List<Map<String, Object>> maps = purchaseOrderMapper.selectCountGroupbyDeliveryStatus(pageReqVO);
            if (CommonUtil.isNotEmpty(maps)) {
                maps.forEach(item ->
                        resultMap.put((String) item.get("deliveryStatus"), (Long) item.get("orderCount")));
            }
        }
        return resultMap;
    }

    @Override
    public PageResult<SupplierMonthOrderRespVO> pageMonth(SupplierMonthOrderPageReqVO pageReqVO, Long supplierId) {
        return purchaseOrderMapper.pageMonth(pageReqVO, supplierId);
    }

    /**
     * 确认对账
     *
     * @param purchaseOrderList 采购订单id集合
     * @param supplierId        当前供应商id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reconciliation(List<ErpPurchaseOrderDO> purchaseOrderList, Long supplierId) {
        if (CommonUtil.isEmpty(purchaseOrderList)) {
            throw exception(PURCHASE_ORDER_NOT_EXISTS);
        }
        Set<Long> validIds = new HashSet<>();
        for (ErpPurchaseOrderDO order : purchaseOrderList) {
            if (!supplierId.equals(order.getSupplierId())) {
                throw exception(PURCHASE_SUPPLIER_OWN_ERROR);
            }
            if (ErpDeliveryStatus.ARRIVAL.getStatus().equals(order.getDeliveryStatus())) {
                validIds.add(order.getId());
            }
        }
        if (CommonUtil.isEmpty(validIds)) {
            throw exception(PURHCASE_NO_EXISTS_ARRIVAL);
        }

        List<ErpPurchaseOrderDO> updateBatch = new ArrayList<>();
        for (ErpPurchaseOrderDO item : purchaseOrderList) {
            ErpPurchaseOrderDO updateInfo = new ErpPurchaseOrderDO();
            updateInfo.setId(item.getId());
            updateInfo.setDeliveryStatus(ErpDeliveryStatus.RECONCILIATION.getStatus());
            updateBatch.add(updateInfo);
        }
        purchaseOrderMapper.updateBatch(updateBatch);
    }

    @Override
    public Map<Long, ErpPurchaseOrderDO> getMap(List<Long> ids) {
        if (CommonUtil.isEmpty(ids)) {
            return new HashMap<>(1);
        }
        List<ErpPurchaseOrderDO> erpPurchaseOrderDOS = purchaseOrderMapper.selectByIds(ids);
        return CommonUtil.listConvertMap(erpPurchaseOrderDOS, ErpPurchaseOrderDO::getId);
    }

    @Override
    public void abnormalPurchaseOrder(Long purchaseOrderId) {
        purchaseOrderMapper.update(Wrappers.<ErpPurchaseOrderDO>lambdaUpdate()
                .set(ErpPurchaseOrderDO::getCheckTaskStatus, CheckTaskStatus.ABNORMAL.getKey())
                .set(ErpPurchaseOrderDO::getDeliveryStatus, ErpDeliveryStatus.NOT_YET.getStatus())
                .eq(ErpPurchaseOrderDO::getId, purchaseOrderId));
    }

    @Async
    @TransactionalEventListener(classes = PurchaseOrderSplitEvent.class, phase = TransactionPhase.AFTER_COMMIT)
    public void orderSplit(PurchaseOrderSplitEvent event) {
        log.warn("采购订单拆分:{}", event);
        Long orderId = event.getCustomerOrderId();
        CustomerOrderDTO customerOrderDTO = customerOrderApi.queryById(orderId);
        List<CustomerOrderItemDTO> customerOrderItemDTOS = customerOrderApi.queryItemsByOrderId(orderId);

        if (CommonUtil.isEmpty(customerOrderItemDTOS) || CommonUtil.isEmpty(customerOrderDTO)) {
            return ;
        }

        Map<Long, List<CustomerOrderItemDTO>> supplierMap = CommonUtil.listConvertListMap(customerOrderItemDTOS, CustomerOrderItemDTO::getSupplierId);
        List<Long> purchaseOrderIds = new ArrayList<>();
        for (Map.Entry<Long, List<CustomerOrderItemDTO>> entry : supplierMap.entrySet()) {
            Long supplierId = entry.getKey();
            List<CustomerOrderItemDTO> list = entry.getValue();
            ErpPurchaseOrderSaveReqVO purchaseOrder = new ErpPurchaseOrderSaveReqVO();
            purchaseOrder.setSupplierId(supplierId);
            purchaseOrder.setOrderTime(customerOrderDTO.getCreateTime());
            purchaseOrder.setDepositPrice(list.stream().mapToInt(CustomerOrderItemDTO::getOrderItemTotal).sum());
            purchaseOrder.setCustomerOrderId(orderId);
            purchaseOrder.setDeliveryStatus(ErpDeliveryStatus.MATCHED.getStatus());

            for (CustomerOrderItemDTO customerOrderItem : list) {
                ErpPurchaseOrderSaveReqVO.Item purhcaseOrderItem = new ErpPurchaseOrderSaveReqVO.Item();
                purhcaseOrderItem.setProductId(customerOrderItem.getProductId());
                purhcaseOrderItem.setProductUnit(customerOrderItem.getProductInfo().getUnitName());
                purhcaseOrderItem.setProductPrice(customerOrderItem.getOrderItemPrice());
                purhcaseOrderItem.setCount(customerOrderItem.getOrderItemQuantity());
                purhcaseOrderItem.setCustomerOrderItemId(customerOrderItem.getId());
                purhcaseOrderItem.setRemark(customerOrderItem.getCustomerRemark());
                purchaseOrder.put(purhcaseOrderItem);
            }

            ErpPurchaseOrderServiceImpl proxyService = SpringUtils.getBean(ErpPurchaseOrderServiceImpl.class);
            Long purchaseOrderId = this.createPurchaseOrder(purchaseOrder);

            CustomerOrderRecordEvent recordEvent = new CustomerOrderRecordEvent();
            recordEvent.setOrderStatus(CustomerOrderStatus.ORDER_MATCH);
            recordEvent.setCustomerOrderId(orderId);
            recordEvent.setSupplierId(supplierId);
            recordEvent.setCopyWriter(CommonUtil.asList(list.get(0).getSupplierName()));
            orderRecordApi.recordEvent(recordEvent);

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            // 通过代理对象调用，事务生效
            proxyService.delivery(SupplierPurchaseOrderDeliveryReqVO.transform(CommonUtil.asList(purchaseOrderId)), supplierId,
                    ErpDeliveryStatus.MATCHED, ErpDeliveryStatus.NOT_YET, CustomerOrderStatus.SUPPLIER_ACCEPT_ORDER);
        }
    }
}
