package com.fjhx.sale.service.purchase.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.account.entity.account.po.AccountManagement;
import com.fjhx.account.service.account.AccountManagementService;
import com.fjhx.area.utils.CustomizeAreaUtil;
import com.fjhx.common.constant.SourceConstant;
import com.fjhx.common.entity.AvailableStockBo;
import com.fjhx.common.entity.corporation.po.Corporation;
import com.fjhx.common.entity.documentary.bo.DocumentaryData;
import com.fjhx.common.enums.FlowStatusEnum1;
import com.fjhx.common.service.corporation.CorporationService;
import com.fjhx.common.service.documentary.GetDocumentaryBusinessTemplate;
import com.fjhx.common.utils.Assert;
import com.fjhx.flow.entity.flow.po.FlowExample;
import com.fjhx.flow.enums.FlowStatusEnum;
import com.fjhx.flow.service.flow.FlowExampleService;
import com.fjhx.item.enums.ProductAvailableRecordType;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.purchase.entity.invoice.po.InvoiceDetails;
import com.fjhx.purchase.entity.invoice.vo.InvoiceDetailsVo;
import com.fjhx.purchase.entity.pay.po.Pay;
import com.fjhx.purchase.entity.pay.po.PayDetail;
import com.fjhx.purchase.entity.pay.vo.PayDetailVo;
import com.fjhx.purchase.entity.pay.vo.PayVo;
import com.fjhx.purchase.entity.purchase.bo.PurchaseDocumentaryBo;
import com.fjhx.purchase.entity.purchase.enums.PurchaseDataResourceEnum;
import com.fjhx.purchase.entity.purchase.enums.PurchaseStatusEnum;
import com.fjhx.purchase.entity.subscribe.enums.SubscribeDetailStatusEnum;
import com.fjhx.purchase.entity.subscribe.po.Subscribe;
import com.fjhx.purchase.entity.subscribe.po.SubscribeDetail;
import com.fjhx.purchase.mapper.subscribe.SubscribeDetailMapper;
import com.fjhx.purchase.service.invoice.InvoiceDetailsService;
import com.fjhx.purchase.service.pay.PayDetailService;
import com.fjhx.purchase.service.pay.PayService;
import com.fjhx.purchase.service.subscribe.SubscribeDetailService;
import com.fjhx.purchase.service.subscribe.SubscribeService;
import com.fjhx.sale.entity.contract.dto.ContractSelectDto;
import com.fjhx.sale.entity.contract.po.Contract;
import com.fjhx.sale.entity.contract.vo.ContractBudgetVo;
import com.fjhx.sale.entity.pack.po.PackDetail;
import com.fjhx.sale.entity.pack.po.PackDetailProduct;
import com.fjhx.sale.entity.pack.vo.PackDetailProductVo;
import com.fjhx.sale.entity.purchase.dto.EhsdPurchaseDto;
import com.fjhx.sale.entity.purchase.dto.EhsdPurchaseSelectDto;
import com.fjhx.sale.entity.purchase.po.EhsdPurchase;
import com.fjhx.sale.entity.purchase.po.EhsdPurchaseProduct;
import com.fjhx.sale.entity.purchase.po.EhsdPurchaseProductMountings;
import com.fjhx.sale.entity.purchase.po.EhsdPurchaseProject;
import com.fjhx.sale.entity.purchase.vo.EhsdPurchaseDocumentaryVo;
import com.fjhx.sale.entity.purchase.vo.EhsdPurchaseProductVo;
import com.fjhx.sale.entity.purchase.vo.EhsdPurchaseVo;
import com.fjhx.sale.mapper.purchase.EhsdPurchaseMapper;
import com.fjhx.sale.service.contract.ContractService;
import com.fjhx.sale.service.pack.PackDetailProductService;
import com.fjhx.sale.service.pack.PackDetailService;
import com.fjhx.sale.service.purchase.EhsdPurchaseProductMountingsService;
import com.fjhx.sale.service.purchase.EhsdPurchaseProductService;
import com.fjhx.sale.service.purchase.EhsdPurchaseProjectService;
import com.fjhx.sale.service.purchase.EhsdPurchaseService;
import com.fjhx.supply.entity.supplier.po.SupplierInfo;
import com.fjhx.supply.entity.supplier.po.SupplierPrice;
import com.fjhx.supply.entity.supplier.vo.SupplierPriceVo;
import com.fjhx.supply.service.supplier.SupplierInfoService;
import com.fjhx.supply.service.supplier.SupplierPriceService;
import com.fjhx.tenant.utils.DeptUstil;
import com.fjhx.wms.entity.stock.po.StockWait;
import com.fjhx.wms.service.stock.StockWaitService;
import com.ruoyi.common.core.domain.BasePo;
import com.ruoyi.common.core.domain.BaseSelectDto;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.wrapper.IWrapper;
import com.ruoyi.common.utils.wrapper.SqlField;
import com.ruoyi.system.utils.UserUtil;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 * ehsd采购表 服务实现类
 * </p>
 *
 * @author
 * @since 2023-05-17
 */
@Service
//@DS(SourceConstant.SALE)
public class EhsdPurchaseServiceImpl extends ServiceImpl<EhsdPurchaseMapper, EhsdPurchase> implements EhsdPurchaseService, GetDocumentaryBusinessTemplate {

    @Autowired
    private EhsdPurchaseProductService ehsdPurchaseProductService;
    @Autowired
    private PackDetailProductService packDetailProductService;
    @Autowired
    private PackDetailService packDetailService;
    @Autowired
    private SupplierInfoService supplierInfoService;
    @Autowired
    private PayService payService;
    @Autowired
    private PayDetailService payDetailService;
    @Autowired
    private CorporationService corporationService;
    @Autowired
    private FlowExampleService flowExampleService;
    @Autowired
    private EhsdPurchaseProjectService ehsdPurchaseProjectService;
    @Autowired
    private EhsdPurchaseService ehsdPurchaseService;
    @Autowired
    private ProductInfoService productInfoService;
    @Autowired
    private EhsdPurchaseProductMountingsService ehsdPurchaseProductMountingsService;
    @Autowired
    private InvoiceDetailsService invoiceDetailsService;
    @Autowired
    private SubscribeDetailService subscribeDetailService;
    @Autowired
    private AccountManagementService accountManagementService;
    @Autowired
    private SupplierPriceService supplierPriceService;
    @Autowired
    private ContractService contractService;
    @Autowired
    private SubscribeService subscribeService;
    @Autowired
    private EhsdPurchaseProductService purchaseProductService;
    @Autowired
    private SubscribeDetailMapper subscribeDetailMapper;
    @Autowired
    private StockWaitService stockWaitService;

    /**
     * 分页
     *
     * @param dto
     * @return
     */
    @Override
    public Page<EhsdPurchaseVo> getPage(EhsdPurchaseSelectDto dto) {
        IWrapper<EhsdPurchase> wrapper = getWrapper();
        if (ObjectUtils.isNotEmpty(dto.getStatus())) {
            wrapper.eq("t1", EhsdPurchase::getStatus, dto.getStatus());
        }
        if (ObjectUtils.isNotEmpty(dto.getPayStatus())) {
            wrapper.eq("t1", EhsdPurchase::getPayStatus, dto.getPayStatus());
        }
        if (ObjectUtils.isNotEmpty(dto.getKeyword())) {
            wrapper.keyword(dto.getKeyword(), new SqlField("t2.name"), new SqlField("t1.`code`"));
        }

        if (ObjectUtils.isEmpty(dto.getStatus()) || FlowStatusEnum1.UPDATE.getKey() != dto.getStatus()) {
            //不显示已变更数据
            wrapper.ne(EhsdPurchase::getStatus, FlowStatusEnum1.UPDATE.getKey());
        }

        //权限过滤：采购-子公司看自己的,总公司看全部
        Long companyId = SecurityUtils.getCompanyId();
        if (!Objects.equals(companyId, 100L)) {
            wrapper.eq("t1", EhsdPurchase::getCompanyId, companyId);
        } else {
            wrapper.eq("t1", EhsdPurchase::getCompanyId, dto.getCompanyId());
        }

        wrapper.orderByDesc("t1", EhsdPurchase::getCreateTime);

        //过滤作废的数据
        wrapper.ne("t1", EhsdPurchase::getStatus, FlowStatusEnum1.CANCELLATION.getKey());

        Page<EhsdPurchaseVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<EhsdPurchaseVo> records = page.getRecords();
        if (ObjectUtils.isEmpty(records)) {
            return page;
        }
        //  赋值流程id
        flowExampleService.setFlowId(records, EhsdPurchaseVo::setFlowId);

        //赋值以付款金额
        List<Long> pids = records.stream().map(EhsdPurchaseVo::getId).collect(Collectors.toList());
        List<PayDetailVo> payDetailVoList = payDetailService.getSumMoneyByPurchaseIds(pids);
        Map<Long, BigDecimal> payMap = payDetailVoList.stream().collect(Collectors.toMap(PayDetailVo::getPurchaseId, PayDetailVo::getSumMoney));
        records.forEach(item -> item.setSumPayMoney(payMap.getOrDefault(item.getId(), BigDecimal.ZERO)));

        //赋值用户名称
        UserUtil.assignmentNickName(records, EhsdPurchase::getCreateUser, EhsdPurchase::setUserName);

        //获取生产公司信息
        List<Long> companyIds = records.stream().map(EhsdPurchase::getCompanyId).collect(Collectors.toList());
        Map<Long, String> companyNameMap = DeptUstil.getDeptNameMap(companyIds);

        for (EhsdPurchaseVo record : records) {
            //赋值生产公司名称
            record.setCompanyName(companyNameMap.get(record.getCompanyId()));
        }

        return page;
    }

    @Override
    public EhsdPurchaseVo detail(Long id) {
        EhsdPurchase ehsdPurchase = this.getById(id);
        EhsdPurchaseVo result = BeanUtil.toBean(ehsdPurchase, EhsdPurchaseVo.class);

        //赋值销售订单号
        String saleCode = "";
        if (Objects.equals(result.getDataResource(), 0)) {
            Subscribe subscribe = subscribeService.getById(result.getDataResourceId());
            if (ObjectUtil.isNotEmpty(subscribe)) {
                saleCode = subscribe.getCode();
            }
        } else {
            Contract contract = contractService.getById(result.getDataResourceId());
            if (ObjectUtil.isNotEmpty(contract)) {
                saleCode = contract.getCode();
            }
        }

        List<Long> ids = new ArrayList<>();
        ids.add(result.getSellCountryId());
        ids.add(result.getSellProvinceId());
        ids.add(result.getSellCityId());
        Map<Long, String> areaMapByIds = CustomizeAreaUtil.getAreaMapByIds(ids);
        //赋值卖方地址
        result.setSellCountryName(areaMapByIds.get(result.getSellCountryId()));
        result.setSellProvinceName(areaMapByIds.get(result.getSellProvinceId()));
        result.setSellCityName(areaMapByIds.get(result.getSellCityId()));

        //赋值卖方名称
        SupplierInfo supplierInfo = supplierInfoService.getById(result.getSellCorporationId());
        if (ObjectUtils.isNotEmpty(supplierInfo)) {
            result.setSellCorporationName(supplierInfo.getName());
            result.setSellCorporationName(supplierInfo.getName());
            result.setSellContactName(supplierInfo.getContactPerson());
            result.setSellContactNumber(supplierInfo.getContactNumber());
            result.setSellCorporationFax(supplierInfo.getFax());
            ;
            result.setAddress(supplierInfo.getAreaDetail());
        }
        //赋值卖方（供应商）银行信息
        result.setOpeningBank(supplierInfo.getOpeningBank());//开户银行
        result.setOpeningName(supplierInfo.getOpeningName());//账户名
        result.setContactPerson(supplierInfo.getContactPerson());//联系人
        result.setAccountOpening(supplierInfo.getAccountOpening());//账户
        //赋值买方名称
        Corporation corporation = corporationService.getById(result.getBuyCorporationId());
        if (ObjectUtils.isNotEmpty(corporation)) {
            result.setBuyCorporationName(corporation.getName());
        }
        //赋值采购明细
        List<EhsdPurchaseProduct> ehsdPurchaseProductList = ehsdPurchaseProductService.list(q ->
                q.eq(EhsdPurchaseProduct::getPurchaseId, ehsdPurchase.getId())
        );
        List<EhsdPurchaseProductVo> ehsdPurchaseProductVos = BeanUtil.copyToList(ehsdPurchaseProductList, EhsdPurchaseProductVo.class);
        //赋值产品配件信息
        if (ObjectUtils.isNotEmpty(ehsdPurchaseProductList)) {
            List<Long> eppIds = ehsdPurchaseProductVos.stream().map(EhsdPurchaseProductVo::getId).collect(Collectors.toList());
            Map<Long, List<EhsdPurchaseProductMountings>> eppMap = ehsdPurchaseProductMountingsService.mapKGroup(
                    EhsdPurchaseProductMountings::getPurchaseProductId, q -> q
                            .in(EhsdPurchaseProductMountings::getPurchaseProductId, eppIds)
            );
            for (EhsdPurchaseProductVo ehsdPurchaseProductVo : ehsdPurchaseProductVos) {
                List<EhsdPurchaseProductMountings> ehsdPurchaseProductMountings = eppMap.get(ehsdPurchaseProductVo.getId());
                ehsdPurchaseProductVo.setPurchaseProductMountingsList(ehsdPurchaseProductMountings);

                //赋值销售订单号
                ehsdPurchaseProductVo.setSaleCode(saleCode);
            }
        }

        //赋值产品待采购数量信息
        if (ObjectUtils.isNotEmpty(ehsdPurchaseProductVos)) {
            //合同和申购来源都是申购明细表
            List<Long> subscribeDetailSourceIds = ehsdPurchaseProductVos.stream().map(EhsdPurchaseProductVo::getSubscribeDetailId).distinct().collect(Collectors.toList());
            Map<Long, SubscribeDetail> contractProductMap = subscribeDetailService.mapKEntity(SubscribeDetail::getId, q -> q.in(SubscribeDetail::getId, subscribeDetailSourceIds));
            for (EhsdPurchaseProductVo ehsdPurchaseProductVo : ehsdPurchaseProductVos) {
                BigDecimal count = BigDecimal.ZERO;
                Long subscribeDetailId = ehsdPurchaseProductVo.getSubscribeDetailId();
                SubscribeDetail subscribeDetail = contractProductMap.get(subscribeDetailId);
                if (ObjectUtil.isNotEmpty(subscribeDetail)) {
                    count = subscribeDetail.getCount();
                }
                //获取已采购数量
                List<EhsdPurchaseProduct> ehsdPurchaseProductList1 = ehsdPurchaseProductService.list(q -> q.eq(EhsdPurchaseProduct::getDataResource, 0).eq(EhsdPurchaseProduct::getSubscribeDetailId, subscribeDetailId));
                BigDecimal add = ObjectUtils.isEmpty(ehsdPurchaseProductList1) ? BigDecimal.ZERO : ehsdPurchaseProductList1.stream().map(EhsdPurchaseProduct::getQuantity).reduce(BigDecimal.ZERO, BigDecimal::add);
                ehsdPurchaseProductVo.setExpendQuantity(count.subtract(add));
            }
        }

        //赋值产品信息
        productInfoService.attributeAssign(ehsdPurchaseProductVos, EhsdPurchaseProductVo::getProductId, (item, product) -> {
            item.setDefinition(product.getDefinition());
            item.setProductCode(product.getCustomCode());
            item.setProductSpec(product.getSpec());
            item.setProductLength(product.getLength());
            item.setProductWidth(product.getWidth());
            item.setProductHeight(product.getHeight());
        });
        result.setPurchaseProductList(ehsdPurchaseProductVos);
        //赋值出货明细
        List<Long> cpIds = ehsdPurchaseProductVos.stream().map(EhsdPurchaseProductVo::getDataResourceId).collect(Collectors.toList());
        List<PackDetailProduct> packDetailProductList = packDetailProductService.list(q ->
                q.in(PackDetailProduct::getContractProductId, cpIds)
        );
        List<PackDetailProductVo> packDetailProductVos = BeanUtil.copyToList(packDetailProductList, PackDetailProductVo.class);
        //赋值出货时间
        if (ObjectUtils.isNotEmpty(packDetailProductVos)) {
            PackDetail packDetail = packDetailService.getById(packDetailProductVos.get(0).getPackDetailId());
            packDetailProductVos.forEach(item -> item.setShipmentTime(packDetail.getShipmentTime()));
        }
        result.setPackDetailProductList(packDetailProductVos);


        //赋值其他收费项目
        List<EhsdPurchaseProject> ehsdPurchaseProjects = ehsdPurchaseProjectService.list(q -> q.eq(EhsdPurchaseProject::getPurchaseId, id));
        result.setPurchaseProjectList(ehsdPurchaseProjects);

        //赋值创建人名称
        Map<Long, SysUser> nickNameMapByIds = UserUtil.getMapByIds(Arrays.asList(result.getCreateUser()));
        SysUser sysUser = nickNameMapByIds.get(result.getCreateUser());
        if (ObjectUtil.isNotEmpty(sysUser)) {
            result.setCreateUserName(sysUser.getNickName());
            result.setCreateUserPhone(sysUser.getPhonenumber());
        }

        //赋值历史毛利图信息
        IWrapper<Contract> wrapper = IWrapper.<Contract>getWrapper().eq("t1.contractId", result.getDataResourceId());
        Page<ContractBudgetVo> profitBudgetPage = contractService.getProfitBudgetPage(new ContractSelectDto(), wrapper);
        List<ContractBudgetVo> records = profitBudgetPage.getRecords();
        if (ObjectUtil.isNotEmpty(records)) {
            ContractBudgetVo contractBudgetVo = records.get(0);
            List<ContractBudgetVo.GrossProfitInfo> grossProfitInfoList = contractBudgetVo.getGrossProfitInfoList();
            result.setGrossProfitInfoList(grossProfitInfoList);
        }

        return result;
    }

    /**
     * 详情
     *
     * @param id
     * @return
     */
    @Override
    public PayVo payDetail(Long id) {
        Pay pay = payService.getById(id);
        if (pay == null) {
            throw new ServiceException("没有找到采购付款记录");
        }

        PayVo result = BeanUtil.toBean(pay, PayVo.class);

        // 赋值供应商名称
        SupplierInfo supplierInfo = supplierInfoService.getById(pay.getSupplyId());
        result.setSupplyName(supplierInfo.getName());

        // 赋值采购付款明细
        List<PayDetail> payDetailList = payDetailService.list(q -> q.eq(PayDetail::getPayId, id));
        List<PayDetailVo> payDetailVoList = BeanUtil.copyToList(payDetailList, PayDetailVo.class);
        result.setPayDetailVoList(payDetailVoList);

        if (payDetailVoList.size() == 0) {
            return result;
        }

        // 赋值采购付款明细采购合同编号、采购合同金额
        ehsdPurchaseService.attributeAssign(payDetailVoList, PayDetail::getPurchaseId, (item, purchase) -> {
            item.setPurchaseCode(purchase.getCode());
            item.setPurchaseAmount(purchase.getAmount());
        });

        // 赋值采购付款明细已收发票金额
        List<Long> purchaseIdList = payDetailVoList.stream()
                .map(PayDetail::getPurchaseId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        if (purchaseIdList.size() == 0) {
            return result;
        }

        //赋值已付款金额
        Map<Long, List<PayDetail>> payDetailMap = payDetailService.mapKGroup(PayDetail::getPurchaseId, q -> q.in(PayDetail::getPurchaseId, purchaseIdList));
        for (PayDetailVo payDetail : payDetailVoList) {
            List<PayDetail> payDetail1 = payDetailMap.get(payDetail.getPurchaseId());
            BigDecimal sumMoney = payDetail1.stream().map(PayDetail::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            payDetail.setSumMoney(sumMoney);
        }

        List<InvoiceDetails> list = invoiceDetailsService.list(q -> q.in(InvoiceDetails::getPurchaseId, purchaseIdList));
        Map<Long, BigDecimal> invoiceAmountMap = list.stream().collect(Collectors.toMap(
                InvoiceDetails::getPurchaseId,
                InvoiceDetails::getMoney,
                BigDecimal::add
        ));
        payDetailVoList.forEach(item -> item.setInvoiceAmount(invoiceAmountMap.getOrDefault(item.getPurchaseId(), BigDecimal.ZERO)));

        //赋值流程ID
        DynamicDataSourceContextHolder.push(SourceConstant.BASE);
        FlowExample flowExample = flowExampleService.getOne(Wrappers.<FlowExample>query().lambda().eq(FlowExample::getBusinessId, id));
        // 赋值流程id
        if (ObjectUtil.isNotEmpty(flowExample)) {
            result.setFlowExampleId(flowExample.getId());
        }


        //赋值付款账户名称
        AccountManagement accountManagement = accountManagementService.getById(result.getAccountManagementId());
        if (ObjectUtils.isNotEmpty(accountManagement)) {
            result.setAccountManagementName(accountManagement.getName());
        }


        return result;
    }

    @Override
    public void add(EhsdPurchaseDto ehsdPurchaseDto) {
        this.save(ehsdPurchaseDto);
    }

    @Override
    public void edit(EhsdPurchaseDto ehsdPurchaseDto) {
        this.updateById(ehsdPurchaseDto);
    }

    @Override
    public void delete(Long id) {
        this.removeById(id);
    }

    /**
     * 采购合同作废
     */
    @DSTransactional
    @Override
    public void cancellation(Long id) {
        EhsdPurchase purchase = getById(id);
        Assert.notEmpty(purchase, "查询不到采购信息");
        if (ObjectUtil.isNotEmpty(purchase) && purchase.getPayStatus() != 0) {
            throw new ServiceException("采购合同已付款，禁止作废");
        }

        //修改流程审批状态
        flowExampleService.update(q -> q
                .eq(FlowExample::getId, purchase.getFlowId())
                .in(FlowExample::getStatus, 0, 1)
                .set(FlowExample::getStatus, FlowStatusEnum.CANCELLATION.getKey())
                .set(BasePo::getUpdateTime, new Date())
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );

        //如果审批中作废
        if (Objects.equals(FlowStatusEnum1.UNDER_REVIEW.getKey(), purchase.getStatus())) {
            ehsdPurchaseService.update(q -> q
                    .eq(EhsdPurchase::getId, id)
                    .set(EhsdPurchase::getStatus, FlowStatusEnum1.CANCELLATION.getKey())
                    .set(EhsdPurchase::getUpdateTime, new Date())
                    .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
            );

            //恢复原合同
            Long oldPurchaseId = purchase.getOldPurchaseId();
            if (ObjectUtil.isNotEmpty(oldPurchaseId)) {
                ehsdPurchaseService.update(q -> q
                        .eq(BasePo::getId, oldPurchaseId)
                        .set(EhsdPurchase::getStatus, FlowStatusEnum1.PASS.getKey())
                        .set(BasePo::getUpdateTime, new Date())
                        .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
                );
            }
            return;
        }

        this.update(q -> q
                .eq(EhsdPurchase::getId, id)
                .set(EhsdPurchase::getStatus, FlowStatusEnum1.CANCELLATION.getKey())
                .set(BasePo::getUpdateTime, new Date())
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );

        //修改可用库存
        List<AvailableStockBo> inOutBoList = new ArrayList<>();
        List<EhsdPurchaseProduct> purchaseProductList = purchaseProductService.list(q -> q.eq(EhsdPurchaseProduct::getPurchaseId, id));
        for (EhsdPurchaseProduct purchaseProduct : purchaseProductList) {
            //如果数据来源是申购 操作可用库存(可用库存 = 当前可用库存 - 采购明细数量)
            if (Objects.equals(purchaseProduct.getDataResource(), PurchaseDataResourceEnum.DATA_RESOURCE_0.getKey())) {
                AvailableStockBo inOutBo = new AvailableStockBo();
                inOutBo.setProductId(purchaseProduct.getProductId());
                inOutBo.setQuantity(purchaseProduct.getQuantity());
                inOutBoList.add(inOutBo);
            }

//            //如果数据来源是合同 操作可用库存(可用库存 = 当前可用库存 - 采购超采量)
//            if (Objects.equals(purchaseProduct.getDataResource(), PurchaseDataResourceEnum.DATA_RESOURCE_1.getKey())) {
//                AvailableStockBo inOutBo = new AvailableStockBo();
//                inOutBo.setProductId(purchaseProduct.getProductId());
//                inOutBo.setQuantity(purchaseProduct.getExceedQuantity());
//                inOutBoList.add(inOutBo);
//            }
        }
        productInfoService.editAvailableQuantity(inOutBoList, id, ProductAvailableRecordType.PURCHASE_CANCEL, purchase.getCompanyId());
        //检查待入库是否存在，已入库或者部分入库的数据
        if (stockWaitService.count(q -> q.eq(StockWait::getPurchaseId, purchase.getId()).ne(StockWait::getStatus, 0)) > 0) {
            throw new ServiceException("该采购，已部分入库/已入库 禁止作废！");
        }
        //同时删除待入库数据
        stockWaitService.remove(q -> q.eq(StockWait::getPurchaseId, purchase.getId()));

        //修改申购明细状态
        updateSubscribeStatus(id);
    }

    /**
     * 修改申购明细状态
     */
    @Override
    public void updateSubscribeStatus(Long businessId) {
        //修改申购明细状态
        List<Long> subscribeDetailIds = purchaseProductService.listObject(EhsdPurchaseProduct::getSubscribeDetailId, q -> q
                .eq(EhsdPurchaseProduct::getPurchaseId, businessId)
        );
        //获取已采购数量
        List<SubscribeDetail> purchaseCountByIds = subscribeDetailMapper.getPurchaseCountByIds(subscribeDetailIds);
        Map<Long, BigDecimal> purchaseCountMap = purchaseCountByIds.stream().collect(Collectors.toMap(SubscribeDetail::getId, SubscribeDetail::getCount));
        //修改状态
        List<SubscribeDetail> subscribeDetails = subscribeDetailService.listByIds(subscribeDetailIds);
        for (SubscribeDetail subscribeDetail : subscribeDetails) {
            //获取已采购数并计算状态
            BigDecimal count = purchaseCountMap.getOrDefault(subscribeDetail.getId(), BigDecimal.ZERO);
            if (count.compareTo(subscribeDetail.getCount()) >= 0) {
                //修改为已采购
                subscribeDetail.setStatus(SubscribeDetailStatusEnum.PURCHASED.getKey());
            } else {
                //修改为部分采购
                subscribeDetail.setStatus(SubscribeDetailStatusEnum.LITT_PAID_AMOUNT.getKey());
            }

            if (count.compareTo(BigDecimal.ZERO) == 0) {
                //修改为待采购
                subscribeDetail.setStatus(SubscribeDetailStatusEnum.PAID_AMOUNT.getKey());
            }
        }
        subscribeDetailService.updateBatchById(subscribeDetails);
    }

    /**
     * 根据供应商(卖方)查询无发票的采购合同
     */
    @Override
    public List<EhsdPurchaseVo> getListBySupplyId(String supplyId) {
        if (StringUtils.isEmpty(supplyId)) {
            throw new ServiceException("供应商ID不能为空");
        }
        List<EhsdPurchase> list = this.list(Wrappers.<EhsdPurchase>query().lambda().eq(EhsdPurchase::getSellCorporationId, supplyId).eq(EhsdPurchase::getStatus, PurchaseStatusEnum.PASS.getKey()));

        List<EhsdPurchaseVo> ehsdPurchases = BeanUtil.copyToList(list, EhsdPurchaseVo.class);
        List<Long> ids = list.stream().distinct().map(EhsdPurchase::getId).collect(Collectors.toList());
        List<InvoiceDetailsVo> invoiceDetailsList = invoiceDetailsService.getSumMoneyByPurchaseIds(ids);
        Map<Long, BigDecimal> invoiceMap = invoiceDetailsList.stream().collect(Collectors.toMap(InvoiceDetailsVo::getPurchaseId, InvoiceDetailsVo::getSumMoney));
        List<PayDetailVo> payDetailVoList = payDetailService.getSumMoneyByPurchaseIds(ids);
        Map<Long, BigDecimal> payMap = payDetailVoList.stream().collect(Collectors.toMap(PayDetailVo::getPurchaseId, PayDetailVo::getSumMoney));
        for (EhsdPurchaseVo p : ehsdPurchases) {
            if (MapUtils.isNotEmpty(invoiceMap)) {
                p.setSumInvoiceMoney(invoiceMap.getOrDefault(p.getId(), BigDecimal.ZERO));
            } else {
                p.setSumInvoiceMoney(BigDecimal.ZERO);
            }
            if (MapUtils.isNotEmpty(payMap)) {
                p.setSumPayMoney(payMap.getOrDefault(p.getId(), BigDecimal.ZERO));
            } else {
                p.setSumPayMoney(BigDecimal.ZERO);
            }
        }

        return ehsdPurchases;
    }

    @Override
    public Page<? extends DocumentaryData> getDocumentaryPage(JSONObject selectData, BaseSelectDto
            dto, List<Long> excludeBusinessId) {
        PurchaseDocumentaryBo bo = selectData.toJavaObject(PurchaseDocumentaryBo.class);

        IWrapper<EhsdPurchase> wrapper = IWrapper.getWrapper();
        wrapper.like(EhsdPurchase::getCode, bo.getCode());
        wrapper.eq(EhsdPurchase::getCreateUser, bo.getUserId());
        wrapper.eq(EhsdPurchase::getStatus, 30);
        wrapper.notIn(EhsdPurchase::getId, excludeBusinessId);
        wrapper.orderByDesc(EhsdPurchase::getId);

        Page<EhsdPurchase> itemPage = page(dto.getPage(), wrapper);
        Page<EhsdPurchaseDocumentaryVo> page = PageUtils.copyPage(itemPage, EhsdPurchaseDocumentaryVo.class);
        List<EhsdPurchaseDocumentaryVo> records = page.getRecords();

        if (records.size() == 0) {
            return page;
        }

        // 供应商名称
        supplierInfoService.attributeAssign(records, EhsdPurchase::getSellCorporationId, (item, supplier) -> {
            item.setSupplyName(supplier.getName());
        });

        return page;
    }

    /**
     * 采购id修改
     */
    @Override
    public boolean updatePurchaseId(Long id, Long newId, Long userId, Long oldPurchaseId) {
        return baseMapper.updatePurchaseId(id, newId, userId, oldPurchaseId);
    }

    /**
     * 获取产品采购指导价
     */
    @Override
    public Map<Long, Map<String, Object>> getProductPriceInfo(EhsdPurchaseDto dto) {
        List<Long> productIds = dto.getProductIds();

        //产品在该供应商近20条采购价格
        Map<Long, List<EhsdPurchaseProductVo>> supplyPurchaseProductMap = new HashMap<>();
        Long sellCorporationId = dto.getSellCorporationId();
        if (ObjectUtils.isNotEmpty(sellCorporationId)) {
            List<EhsdPurchaseProductVo> supplyPurchaseProductList = baseMapper.getProductPriceInfo(IWrapper.getWrapper()
                    .in("epp.product_id", productIds)
                    .eq(EhsdPurchase::getSellCorporationId, sellCorporationId)
                    .orderByDesc(EhsdPurchase::getCreateTime)
                    .orderByDesc(EhsdPurchase::getId)
                    .last("LIMIT 20")
            );
            supplyPurchaseProductMap =
                    supplyPurchaseProductList.stream().collect(Collectors.groupingBy(EhsdPurchaseProductVo::getProductId));
        }
        //产品近20条采购价格
        List<EhsdPurchaseProductVo> purchaseProductList = baseMapper.getProductPriceInfo(IWrapper.getWrapper()
                .in("epp.product_id", productIds)
                .orderByDesc(EhsdPurchase::getCreateTime)
                .orderByDesc(EhsdPurchase::getId)
                .last("LIMIT 20")
        );
        Map<Long, List<EhsdPurchaseProductVo>> purchaseProductMap =
                purchaseProductList.stream().collect(Collectors.groupingBy(EhsdPurchaseProductVo::getProductId));

        //按价格升序 获取前10供应商
        List<SupplierPriceVo> topPriceList = supplierPriceService.getTopPriceList(productIds, 10);
        Map<Long, List<SupplierPriceVo>> topPriceMap = topPriceList.stream().collect(Collectors.groupingBy(SupplierPrice::getProductInfoId));

        //处理输出数据
        Map<Long, Map<String, Object>> reData = new HashMap<>();
        for (Long productId : productIds) {
            Map<String, Object> data = new HashMap<>();
            //销售给指定客户近3条产品价格
            data.put("supplyPurchaseProductList", supplyPurchaseProductMap.getOrDefault(productId, new ArrayList<>()));
            //该产品近20条销售价格
            data.put("purchaseProductList", purchaseProductMap.getOrDefault(productId, new ArrayList<>()));
            //前10供应商价格
            data.put("topPriceList", topPriceMap.getOrDefault(productId, new ArrayList<>()));

            reData.put(productId, data);
        }

        return reData;
    }


    /**
     * 根据供应商查询无发票的采购合同
     */
    @Override
    public List<EhsdPurchase> getNoInvoiceListBySupplyId(String supplyId) {
        if (StringUtils.isEmpty(supplyId)) {
            throw new ServiceException("供应商ID不能为空");
        }
        List<EhsdPurchase> list = this.list(Wrappers.<EhsdPurchase>query().lambda().eq(EhsdPurchase::getSellCorporationId, supplyId).eq(EhsdPurchase::getStatus, PurchaseStatusEnum.PASS.getKey()).ne(EhsdPurchase::getInvoiceType, "0"));
        List<Long> ids = list.stream().distinct().map(EhsdPurchase::getId).collect(Collectors.toList());
        List<InvoiceDetailsVo> invoiceDetailsList = invoiceDetailsService.getSumMoneyByPurchaseIds(ids);
        Map<Long, BigDecimal> invoiceMap = invoiceDetailsList.stream().collect(Collectors.toMap(InvoiceDetailsVo::getPurchaseId, InvoiceDetailsVo::getSumMoney));
        List<PayDetailVo> payDetailVoList = payDetailService.getSumMoneyByPurchaseIds(ids);
        Map<Long, BigDecimal> payMap = payDetailVoList.stream().collect(Collectors.toMap(PayDetailVo::getPurchaseId, PayDetailVo::getSumMoney));
        for (EhsdPurchase p : list) {
            if (MapUtils.isNotEmpty(invoiceMap)) {
                p.setSumInvoiceMoney(invoiceMap.getOrDefault(p.getId(), BigDecimal.ZERO));
            } else {
                p.setSumInvoiceMoney(BigDecimal.ZERO);
            }
            if (MapUtils.isNotEmpty(payMap)) {
                p.setSumPayMoney(payMap.getOrDefault(p.getId(), BigDecimal.ZERO));
            } else {
                p.setSumPayMoney(BigDecimal.ZERO);
            }
        }

        return list;
    }

}
