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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
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.common.constant.SourceConstant;
import com.fjhx.common.entity.documentary.bo.DocumentaryData;
import com.fjhx.common.enums.CodingRuleEnum;
import com.fjhx.common.service.coding.CodingRuleService;
import com.fjhx.common.service.documentary.GetDocumentaryBusinessTemplate;
import com.fjhx.common.utils.Assert;
import com.fjhx.item.entity.product.vo.ProductInfoVo;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.item.util.excel.util.ExcelUtil;
import com.fjhx.purchase.entity.deliver.DeliverGoodsDetailsPoVo;
import com.fjhx.purchase.entity.invoice.vo.InvoiceDetailsVo;
import com.fjhx.purchase.entity.pay.vo.PayDetailVo;
import com.fjhx.purchase.entity.purchase.PayExportExcel;
import com.fjhx.purchase.entity.purchase.PurchaseJson;
import com.fjhx.purchase.entity.purchase.bo.PurchaseDocumentaryBo;
import com.fjhx.purchase.entity.purchase.dto.PurchaseDto;
import com.fjhx.purchase.entity.purchase.dto.PurchasePayRecordDetailSelectDto;
import com.fjhx.purchase.entity.purchase.dto.PurchaseSelectDto;
import com.fjhx.purchase.entity.purchase.enums.PurchaseStatusEnum;
import com.fjhx.purchase.entity.purchase.po.Purchase;
import com.fjhx.purchase.entity.purchase.po.PurchaseDetail;
import com.fjhx.purchase.entity.purchase.po.PurchasePayRecordDetail;
import com.fjhx.purchase.entity.purchase.po.PurchaseRefundRecord;
import com.fjhx.purchase.entity.purchase.vo.PurchaseDetailVo;
import com.fjhx.purchase.entity.purchase.vo.PurchaseDocumentaryVo;
import com.fjhx.purchase.entity.purchase.vo.PurchasePayRecordDetailVo;
import com.fjhx.purchase.entity.purchase.vo.PurchaseVo;
import com.fjhx.purchase.entity.quality.po.QualityDetail;
import com.fjhx.purchase.entity.subscribe.po.Subscribe;
import com.fjhx.purchase.entity.subscribe.po.SubscribeDetail;
import com.fjhx.purchase.mapper.purchase.PurchaseMapper;
import com.fjhx.purchase.service.WdlyService;
import com.fjhx.purchase.service.arrival.ArrivalDetailService;
import com.fjhx.purchase.service.arrival.ArrivalService;
import com.fjhx.purchase.service.invoice.InvoiceDetailsService;
import com.fjhx.purchase.service.pay.PayDetailService;
import com.fjhx.purchase.service.purchase.PurchaseDetailService;
import com.fjhx.purchase.service.purchase.PurchasePayRecordDetailService;
import com.fjhx.purchase.service.purchase.PurchaseRefundRecordService;
import com.fjhx.purchase.service.purchase.PurchaseService;
import com.fjhx.purchase.service.subscribe.SubscribeDetailService;
import com.fjhx.purchase.service.subscribe.SubscribeService;
import com.fjhx.supply.entity.supplier.po.SupplierInfo;
import com.fjhx.supply.service.supplier.SupplierInfoService;
import com.fjhx.tenant.utils.DictUtils;
import com.fjhx.wms.entity.PurchaseDetailPo;
import com.fjhx.wms.entity.stock.po.Stock;
import com.fjhx.wms.entity.warehouse.po.Warehouse;
import com.fjhx.wms.service.stock.StockService;
import com.fjhx.wms.service.warehouse.WarehouseService;
import com.obs.services.internal.ServiceException;
import com.ruoyi.common.core.domain.BasePo;
import com.ruoyi.common.core.domain.BaseSelectDto;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
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.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * <p>
 * 采购 服务实现类
 * </p>
 *
 * @author
 * @since 2023-04-06
 */
@DS(SourceConstant.PURCHASE)
@Service
public class PurchaseServiceImpl extends ServiceImpl<PurchaseMapper, Purchase>
        implements PurchaseService, GetDocumentaryBusinessTemplate {

    @Autowired
    private SupplierInfoService supplierInfoService;

    @Autowired
    private InvoiceDetailsService invoiceDetailsService;

    @Autowired
    private PayDetailService payDetailService;

    @Autowired
    private PurchaseDetailService purchaseDetailService;

    @Autowired
    private ProductInfoService productInfoService;

    @Autowired
    private ArrivalDetailService arrivalDetailService;

    @Autowired
    WarehouseService warehouseService;

    @Autowired
    ArrivalService arrivalService;
    @Autowired
    SubscribeDetailService subscribeDetailService;
    @Autowired
    SubscribeService subscribeService;


    @Autowired
    private CodingRuleService codingRuleService;
    @Autowired
    private PurchasePayRecordDetailService purchasePayRecordDetailService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private StockService stockService;
    @Autowired
    private PurchaseRefundRecordService purchaseRefundRecordService;
    @Autowired
    private ISysRoleService sysRoleService;
    @Autowired
    private WdlyService wdlyService;

    /**
     * 列表
     *
     * @param dto
     * @return
     */
    @Override
    public Page<PurchaseVo> getPage(PurchaseSelectDto dto) {
        IWrapper<Purchase> wrapper = getWrapper();
        wrapper.orderByDesc("p", Purchase::getCreateTime);
        if (ObjectUtils.isNotEmpty(dto.getPurchaseStatus())) {
            wrapper.eq("p", Purchase::getPurchaseStatus, dto.getPurchaseStatus());
        }
        if (ObjectUtils.isNotEmpty(dto.getArrivalStatus())) {
            wrapper.eq("p", Purchase::getArrivalStatus, dto.getArrivalStatus());
        }
        if (ObjectUtils.isNotEmpty(dto.getPayStatus())) {
            wrapper.eq("p", Purchase::getPayStatus, dto.getPayStatus());
        }
        wrapper.eq("p", Purchase::getCode, dto.getKeyword());//根据采购单号关键字搜索
        Page<PurchaseVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<PurchaseVo> list = page.getRecords();
        if (CollectionUtils.isNotEmpty(list)) {
            List<Long> supplyIds = list.stream().map(PurchaseVo::getSupplyId).collect(Collectors.toList());
            List<SupplierInfo> supplierInfoList = supplierInfoService.list(Wrappers.<SupplierInfo>query().lambda().in(SupplierInfo::getId, supplyIds));
            Map<Long, List<SupplierInfo>> supplyMap = supplierInfoList.stream().distinct().collect(Collectors.groupingBy(SupplierInfo::getId));
            if (MapUtils.isNotEmpty(supplyMap)) {
                for (PurchaseVo p : list) {
                    List<SupplierInfo> supplys = supplyMap.getOrDefault(p.getSupplyId(), null);
                    p.setSupplyName(supplys == null ? null : supplys.get(0).getName());
                }
            }
        }
        return page;
    }

    @Override
    public Page<PurchaseVo> getPageByWdly(PurchaseSelectDto dto) {
        IWrapper<Purchase> wrapper = getWrapper();

        //过滤维多利亚数据
        wrapper.isNotNull("p.victoriatourist_json");

        wrapper.orderByDesc("p", Purchase::getCreateTime);
        if (ObjectUtils.isNotEmpty(dto.getPurchaseStatus())) {
            wrapper.in("p", Purchase::getPurchaseStatus, dto.getPurchaseStatus().split(","));
        }
        if (ObjectUtils.isNotEmpty(dto.getArrivalStatus())) {
            wrapper.eq("p", Purchase::getArrivalStatus, dto.getArrivalStatus());
        }
        if (ObjectUtils.isNotEmpty(dto.getPayStatus())) {
            wrapper.eq("p", Purchase::getPayStatus, dto.getPayStatus());
        }

        //采购单号 供应商 采购人
        if (ObjectUtils.isNotEmpty(dto.getKeyword())) {
            //供应商
            List<Long> supplierInfoIds = supplierInfoService.listObject(SupplierInfo::getId, q -> q.like(SupplierInfo::getName, dto.getKeyword()));
            wrapper.and(q -> q.like("json_unquote(p.victoriatourist_json -> '$.contractCode')", dto.getKeyword())
                    .or().in("p", Purchase::getSupplyId, supplierInfoIds)
                    .or().like("p", Purchase::getPurchaseName, dto.getKeyword())
                    //根据明细 产品名称 产品编号 过滤
                    .or().like("pi.name", dto.getKeyword())
                    .or().like("pi.custom_code", dto.getKeyword())
            );
        }
        //高级检索
        //采购单号
        if (ObjectUtils.isNotEmpty(dto.getContractCode())) {
            wrapper.like("json_unquote(p.victoriatourist_json -> '$.contractCode')", dto.getContractCode());
        }
        //供应商
        wrapper.eq("p", Purchase::getSupplyId, dto.getSupplyId());
        //收货仓库
        if (ObjectUtils.isNotEmpty(dto.getReceiptWarehouseId())) {
            wrapper.like("json_unquote(p.victoriatourist_json -> '$.receiptWarehouseId')", dto.getReceiptWarehouseId());
        }
        //采购金额
        wrapper.ge("p", Purchase::getAmount, dto.getStartAmount());
        wrapper.le("p", Purchase::getAmount, dto.getEndAmount());
        //采购人
        wrapper.eq("p", Purchase::getCreateUser, dto.getPurchaseUserId());
        //采购时间
        wrapper.ge("p", Purchase::getCreateTime, dto.getPurchaseStartTime());
        wrapper.le("p", Purchase::getCreateTime, dto.getPurchaseEndTime());

        //是否在途过滤
        if (ObjectUtil.isNotEmpty(dto.getIsTransit())) {
            wrapper.having("(IF(sum( dg.`status` ) != count( dg.`status` ), 1, 0)) = {0}", dto.getIsTransit());
        }

        //添加权限过滤
        DynamicDataSourceContextHolder.push(SourceConstant.BASE);
        Set<String> permissionList = sysRoleService.selectRolePermissionByUserId(SecurityUtils.getUserId());
        DynamicDataSourceContextHolder.poll();
        if (ObjectUtil.isNotEmpty(permissionList)) {
            //if当前用户的角色 in [运营专员, 运营助理] 页面仅展示产品.管理部门 == 当前用户所在部门或下级部门的相关数据
            if (permissionList.contains("E-commerce operation") || permissionList.contains("Operation assistant")) {
                wrapper.and(q -> q.eq("de.dept_id", SecurityUtils.getDeptId())
                        .or()
                        .like("de.ancestors", SecurityUtils.getDeptId()));
            }
        }

        //部门(项目组)过滤
        wrapper.eq("de.dept_id", dto.getDeptId());


        wrapper.groupBy("p.id");
        Page<PurchaseVo> page = new Page<>();
        if (dto.getPageSize() == -1) {
            page.setRecords(baseMapper.getList(wrapper));
        } else {
            page = baseMapper.getPage(dto.getPage(), wrapper);
        }
//        Page<PurchaseVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<PurchaseVo> list = page.getRecords();
        if (ObjectUtils.isEmpty(list)) {
            return page;
        }

        List<Long> supplyIds = list.stream().map(PurchaseVo::getSupplyId).collect(Collectors.toList());
        List<SupplierInfo> supplierInfoList = supplierInfoService.list(Wrappers.<SupplierInfo>query().lambda().in(SupplierInfo::getId, supplyIds));
        Map<Long, List<SupplierInfo>> supplyMap = supplierInfoList.stream().distinct().collect(Collectors.groupingBy(SupplierInfo::getId));
        if (MapUtils.isNotEmpty(supplyMap)) {
            for (PurchaseVo p : list) {
                List<SupplierInfo> supplys = supplyMap.getOrDefault(p.getSupplyId(), null);
                p.setSupplyName(supplys == null ? null : supplys.get(0).getName());
            }
        }

        //维多利亚 赋值收货仓库名称
        List<Long> wids = new ArrayList<>();
        for (PurchaseVo purchaseVo : list) {
            String victoriatouristJson = purchaseVo.getVictoriatouristJson();
            if (ObjectUtils.isNotEmpty(victoriatouristJson)) {
                JSONObject json = JSONObject.parseObject(victoriatouristJson);
                wids.add(json.getLong("receiptWarehouseId"));
            }
        }
        List<Warehouse> warehouses = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(wids)) {
            warehouses = warehouseService.listByIds(wids);
        }
        Map<Long, String> warehousesMap = warehouses.stream().collect(Collectors.toMap(Warehouse::getId, Warehouse::getName));

        //赋值已付款金额
        List<Long> purchaseIds = list.stream().map(PurchaseVo::getId).collect(Collectors.toList());
        Map<Long, List<PurchasePayRecordDetail>> PayRecordMap = purchasePayRecordDetailService.mapKGroup(PurchasePayRecordDetail::getPurchaseId,
                q -> q.in(PurchasePayRecordDetail::getPurchaseId, purchaseIds));

        //赋值退款金额
        Map<Long, List<PurchaseRefundRecord>> refundRecordMap = purchaseRefundRecordService.mapKGroup(PurchaseRefundRecord::getPurchaseId,
                q -> q.in(PurchaseRefundRecord::getPurchaseId, purchaseIds));

        for (PurchaseVo purchaseVo : list) {
            String victoriatouristJson = purchaseVo.getVictoriatouristJson();
            if (ObjectUtils.isNotEmpty(victoriatouristJson)) {
                JSONObject json = JSONObject.parseObject(victoriatouristJson);
                String warehouseName = warehousesMap.get(json.getLong("receiptWarehouseId"));
                json.put("receiptWarehouseName", warehouseName);
                purchaseVo.setVictoriatouristJson(JSONObject.toJSONString(json, JSONWriter.Feature.WriteLongAsString));
            }

            //赋值已付款金额
            List<PurchasePayRecordDetail> purchasePayRecords = PayRecordMap.get(purchaseVo.getId());
            purchaseVo.setPaidAmount(BigDecimal.ZERO);
            if (ObjectUtils.isNotEmpty(purchasePayRecords)) {
                //求和已付款
                BigDecimal paidAmount = purchasePayRecords.stream().map(PurchasePayRecordDetail::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                purchaseVo.setPaidAmount(paidAmount);
            }

            //赋值退款金额
            List<PurchaseRefundRecord> purchaseRefundRecords = refundRecordMap.get(purchaseVo.getId());
            purchaseVo.setRefundAmount(BigDecimal.ZERO);
            if (ObjectUtils.isNotEmpty(purchaseRefundRecords)) {
                //求和已退款
                BigDecimal refundAmount = purchaseRefundRecords.stream().map(PurchaseRefundRecord::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                purchaseVo.setRefundAmount(refundAmount);
            }
        }
        //赋值到货状态
//            List<Long> pids = list.stream().map(PurchaseVo::getId).collect(Collectors.toList());
//            List<Arrival> arrivalList = arrivalService.list(q -> q.in(Arrival::getPurchaseId, pids));
//            Map<Long, List<Arrival>> arrivalMap = arrivalList.stream().collect(Collectors.groupingBy(Arrival::getPurchaseId));
//            for (PurchaseVo purchaseVo : list) {
//                List<Arrival> list1 = arrivalMap.get(purchaseVo.getId());
//                if(ObjectUtils.isEmpty(list1)){
//                    purchaseVo.setArrivalStatus(0);
//                    continue;
//                }
//                List<Arrival> arrivalCount = list1.stream().filter(q -> q.equals(1)).collect(Collectors.toList());
//                if(arrivalCount.size()==0){
//                    //未到货
//                    purchaseVo.setArrivalStatus(0);
//                }else if(arrivalCount.size()<=list1.size()){
//                    //部分到货
//                    purchaseVo.setArrivalStatus(1);
//                }else{
//                    //完全到货
//                    purchaseVo.setArrivalStatus(2);
//                }
//            }

        return page;
    }

    /**
     * 详情
     *
     * @param id
     * @return
     */
    @Override
    public PurchaseVo detail(Long id) {
        Purchase purchase = this.getById(id);
        if (ObjectUtils.isEmpty(purchase)) {
            throw new ServiceException("采购单不存在");
        }
        //查询出供应商名称
        SupplierInfo info = supplierInfoService.getById(purchase.getSupplyId());
        PurchaseVo result = BeanUtil.toBean(purchase, PurchaseVo.class);
        result.setSupplyName(info.getName());
        //查询出采购明细列表
        List<PurchaseDetail> purchaseDetailList = purchaseDetailService.list(Wrappers.<PurchaseDetail>query().lambda().eq(PurchaseDetail::getPurchaseId, id));
        //查询出产品
        if (CollectionUtils.isNotEmpty(purchaseDetailList)) {
            //赋值申购编号
            PurchaseDetail purchaseDetail = purchaseDetailList.get(0);
            SubscribeDetail subscribeDetail = subscribeDetailService.getById(purchaseDetail.getSubscribeDetailId());
            if (ObjectUtils.isNotEmpty(subscribeDetail)) {
                Subscribe subscribe = subscribeService.getById(subscribeDetail.getSubscribeId());
                if (ObjectUtils.isNotEmpty(subscribe)) {
                    result.setSubscribeCode(subscribe.getCode());
                }
            }

            List<Long> productIds = purchaseDetailList.stream().map(PurchaseDetail::getBussinessId).collect(Collectors.toList());
            List<ProductInfoVo> productInfos = productInfoService.getListByProductIds(productIds);
            Map<Long, List<ProductInfoVo>> productMap = productInfos.stream().distinct().collect(Collectors.groupingBy(ProductInfoVo::getId));
            //获取所有仓库次品数量
            Map<Long, List<Stock>> stockMap = stockService.mapKGroup(Stock::getProductId, q -> q.in(Stock::getProductId, productIds));
            List<QualityDetail> purchaseDisqualificationQuantity = baseMapper.getPurchaseDisqualificationQuantity(id);
            Map<Long, BigDecimal> purchaseNoQuantityMap = purchaseDisqualificationQuantity
                    .stream().collect(Collectors.toMap(QualityDetail::getBussinessId, QualityDetail::getNoQualifiedCount));
            if (MapUtils.isNotEmpty(productMap)) {
                for (PurchaseDetail p : purchaseDetailList) {
                    //查询出到货总量
                    BigDecimal sumArrivalCount = arrivalDetailService.getSumCount(p.getId(), p.getBussinessId());
                    p.setSumArrivalCount(sumArrivalCount);
                    List<ProductInfoVo> productInfoVos = productMap.getOrDefault(p.getBussinessId(), null);
                    ProductInfoVo vo = productInfoVos.get(0);
                    p.setProductCode(vo.getCode());
                    p.setProductName(vo.getName());
                    p.setProductType(vo.getType());
                    p.setProductCategory(vo.getClassifyName());
                    p.setProductUnit(vo.getUnit());
                    p.setProductSpec(vo.getSpec());
                    p.setProductCustomCode(vo.getCustomCode());
                    p.setProductDefinition(vo.getDefinition());
                    //赋值产品部门id
                    JSONObject victoriatouristJson = JSONObject.parseObject(vo.getVictoriatouristJson());
                    if (ObjectUtils.isNotEmpty(victoriatouristJson)) {
                        p.setProductDeptId(victoriatouristJson.getLong("deptId"));
                    }
                    //赋值次品数量
                    List<Stock> stockList = stockMap.get(p.getBussinessId());
                    if (ObjectUtils.isNotEmpty(stockList)) {
                        BigDecimal defectiveQuantity = BigDecimal.ZERO;
                        for (Stock stock : stockList) {
                            JSONObject json = JSONObject.parseObject(stock.getVictoriatouristJson());
                            if (ObjectUtils.isNotEmpty(json) && ObjectUtil.isNotEmpty(json.get("defectiveQuantity"))) {
                                defectiveQuantity = defectiveQuantity.add(json.getBigDecimal("defectiveQuantity"));
                            }
                        }
                        p.setDefectiveQuantity(defectiveQuantity);
                    }
                    //赋值申购数量
                    SubscribeDetail subscribeDetail1 = subscribeDetailService.getById(p.getSubscribeDetailId());
                    if (ObjectUtils.isNotEmpty(subscribeDetail1)) {
                        p.setSubscribeQuantity(subscribeDetail1.getCount());
                    }
                    //赋值已采购数量
                    List<PurchaseDetail> list = purchaseDetailService.list(q -> q.eq(PurchaseDetail::getSubscribeDetailId, p.getSubscribeDetailId()));
                    if (ObjectUtils.isNotEmpty(list)) {
                        BigDecimal count = list.stream()
                                .map(PurchaseDetail::getCount)
                                .reduce(BigDecimal.ZERO, BigDecimal::add);
                        p.setPurchaseQuantity(count);
                    }
                    //赋值本次采购次品数
                    BigDecimal purchaseNoQuantity = purchaseNoQuantityMap.getOrDefault(p.getBussinessId(), BigDecimal.ZERO);
                    p.setPurchaseNoQualifiedCount(purchaseNoQuantity);
                }
            }
        }
        result.setPurchaseDetailList(purchaseDetailList);
        return result;
    }

    /**
     * 采购新增
     *
     * @param purchase
     */
    @Override
    public void add(Purchase purchase) {
        PurchaseService purchaseService = SpringUtil.getBean(PurchaseService.class);
        PurchaseDetailService purchaseDetailService = SpringUtil.getBean(PurchaseDetailService.class);
//        purchase.setCode(CodeEnum.PURCHASE.getCode());
        purchase.setCode(codingRuleService.createCode(CodingRuleEnum.PURCHASE.getKey(), null));
        purchase.setPurchaseStatus(PurchaseStatusEnum.UNDER_REVIEW.getKey());
        purchaseService.save(purchase);
        if (CollectionUtils.isNotEmpty(purchase.getPurchaseDetailList())) {
            for (PurchaseDetail s : purchase.getPurchaseDetailList()) {
                s.setPurchaseId(purchase.getId());
            }
            purchaseDetailService.saveBatch(purchase.getPurchaseDetailList());
        }
    }

    @Override
    @DSTransactional
    public void edit(PurchaseDto purchaseDto) {
        this.updateById(purchaseDto);
    }

    @Override
    @DSTransactional
    public void purchaseCorrect(PurchaseDto purchaseDto) {
        //获取提交上来的json
        String dtoPurchaseJsonStr = purchaseDto.getVictoriatouristJson();
        JSONObject dtoPurchaseJson = ObjectUtil.isEmpty(dtoPurchaseJsonStr) ? new JSONObject() : JSONObject.parseObject(dtoPurchaseJsonStr);
        //获取提交上来的采购明细
        List<PurchaseDetail> purchaseDetailList1 = purchaseDto.getPurchaseDetailList();
        Map<Long, PurchaseDetail> dtoPurchaseDetailMap = purchaseDetailList1.stream().collect(Collectors.toMap(PurchaseDetail::getId, Function.identity()));

        //只能修改 采购明细(单价,总金额),其他费用,运费,优惠,采购总金额
        Purchase oldPurchase = getById(purchaseDto.getId());
        String purchaseJsonStr = oldPurchase.getVictoriatouristJson();
        JSONObject victoriatouristJson = ObjectUtil.isEmpty(purchaseJsonStr) ? new JSONObject() : JSONObject.parseObject(purchaseJsonStr);
        //采购总金额
        oldPurchase.setAmount(purchaseDto.getAmount());
        //其他费用
        victoriatouristJson.put("otherFeeList", dtoPurchaseJson.getJSONArray("otherFeeList"));
        //运费
        victoriatouristJson.put("freight", dtoPurchaseJson.getBigDecimal("freight"));
        //优惠
        victoriatouristJson.put("preferential", dtoPurchaseJson.getBigDecimal("preferential"));
        //写入json
        oldPurchase.setVictoriatouristJson(victoriatouristJson.toJSONString());

        //采购明细(单价,总金额)
        List<PurchaseDetail> oldPurchaseDetailList = purchaseDetailService.list(q -> q.eq(PurchaseDetail::getPurchaseId, purchaseDto.getId()));
        for (PurchaseDetail purchaseDetail : oldPurchaseDetailList) {
            PurchaseDetail newPurchaseDetail = dtoPurchaseDetailMap.get(purchaseDetail.getId());
            if (ObjectUtil.isNotEmpty(newPurchaseDetail)) {
                purchaseDetail.setPrice(newPurchaseDetail.getPrice());
                purchaseDetail.setAmount(newPurchaseDetail.getAmount());
            }
        }

        //记录修改数据前
        PurchaseVo detail = detail(purchaseDto.getId());
        JSONArray arrays = ObjectUtil.isEmpty(detail.getOldDataJson()) ? new JSONArray() : JSONArray.parse(detail.getOldDataJson());
        JSONObject json = new JSONObject();
        json.put("updateUser", SecurityUtils.getUserId());
        json.put("updateDate", new Date());
        json.put("version", (arrays.size() + 1));
        json.put("data", JSONObject.toJSONString(detail));
        arrays.add(json);
        oldPurchase.setOldDataJson(arrays.toJSONString());

        //修改数据
        this.updateById(oldPurchase);
        purchaseDetailService.updateBatchById(oldPurchaseDetailList);
    }

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

    /**
     * 根据供应商查询采购合同
     *
     * @param supplyId
     * @return
     */
    @Override
    public List<Purchase> getListBySupplyId(String supplyId) {
        if (StringUtils.isEmpty(supplyId)) {
            throw new ServiceException("供应商ID不能为空");
        }
        List<Purchase> list = this.list(Wrappers.<Purchase>query().lambda().eq(Purchase::getSupplyId, supplyId).eq(Purchase::getPurchaseStatus, PurchaseStatusEnum.PASS.getKey()));
        List<Long> ids = list.stream().distinct().map(Purchase::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 (Purchase p : list) {
            if (MapUtils.isNotEmpty(invoiceMap)) {
                p.setSumInvoiceMoney(invoiceMap.getOrDefault(p.getId(), null));
            } else {
                p.setSumInvoiceMoney(BigDecimal.ZERO);
            }
            if (MapUtils.isNotEmpty(payMap)) {
                p.setSumPayMoney(payMap.getOrDefault(p.getId(), null));
            } else {
                p.setSumPayMoney(BigDecimal.ZERO);
            }
        }

        return list;
    }

    /**
     * 货款账单
     */
    @Override
    public Page<PurchaseDto> paymentBill(PurchaseSelectDto purchaseDto) {
        QueryWrapper<Object> query = Wrappers.query();
        query.eq(ObjectUtil.isNotEmpty(purchaseDto.getSupplyId()), "pu.supply_id", purchaseDto.getSupplyId());
        query.eq(ObjectUtil.isNotEmpty(purchaseDto.getPayStatus()), "pu.pay_status", purchaseDto.getPayStatus());
        query.like(StringUtils.isNotEmpty(purchaseDto.getKeyword()), "pu.code", purchaseDto.getKeyword());
        query.groupBy("pu.id");
        //查询采购信息与已收发票
        Page<PurchaseDto> page = baseMapper.paymentBill(purchaseDto.getPage(), query);
        List<PurchaseDto> records = page.getRecords();
        if (records.size() == 0) {
            return page;
        }
        //获取到所有的采购订单ID
        List<Long> ids = records.stream().map(purchaseDto1 -> purchaseDto1.getId()).collect(Collectors.toList());
        QueryWrapper<Object> wrapper = Wrappers.query();
        wrapper.in("sw.business_id", ids);
        wrapper.eq("sw.type", 1);
        wrapper.groupBy("sw.business_id");
        //查询到货金额(已入库的采购数量*采购单价)
        List<PurchaseDto> purchaseDtos = baseMapper.arrivalAmount(wrapper);
        Map<Long, List<PurchaseDto>> arrivalMap = purchaseDtos.stream().collect(Collectors.groupingBy(PurchaseDto::getId));


        //查询已付款金额（）
        QueryWrapper<Object> queryWrapper = Wrappers.query();
        queryWrapper.in("pd.purchase_id", ids);
        queryWrapper.eq("p.status", 30);
        queryWrapper.groupBy("pd.purchase_id");
        List<PurchaseDto> purchaseDtos1 = baseMapper.paidAmount(queryWrapper);
        Map<Long, List<PurchaseDto>> paidMap = purchaseDtos1.stream().collect(Collectors.groupingBy(PurchaseDto::getId));

        //赋值到货金额与已付款金额
        for (PurchaseDto record : records) {
            //初始化到货金额与已付款金额
            record.setArrivalAmount(new BigDecimal(0));
            record.setPaidAmount(new BigDecimal(0));
            //到货中没有币种选择（使用合同的币种）
            record.setArrivalCurrency(record.getCurrency());
            //已付款金额币种默认合同币种
            record.setPaidCurrency(record.getCurrency());
            //赋值到货金额
            List<PurchaseDto> arrivalList = arrivalMap.get(record.getId());
            if (ObjectUtils.isNotEmpty(arrivalList)) {
                record.setArrivalAmount(arrivalList.get(0).getAmount());
            }

            //赋值已付款金额
            List<PurchaseDto> paidList = paidMap.get(record.getId());
            if (ObjectUtils.isNotEmpty(paidList)) {
                record.setPaidAmount(paidList.get(0).getAmount());
                record.setPaidCurrency(paidList.get(0).getCurrency());
            }
        }

        return page;
    }

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

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

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

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

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

        return page;
    }

    /**
     * 获取已采购 采购人列表
     */
    @Override
    public List<SysUser> getPurchaseUserList() {
        List<Long> createUserIds = listObject(Purchase::getCreateUser, q -> q.groupBy(Purchase::getCreateUser));
        if (ObjectUtils.isEmpty(createUserIds)) {
            return new ArrayList<>();
        }
        List<SysUser> userList = userService.getListByUserId(createUserIds);
        userList.forEach(item -> item.setPassword(null));
        return userList;
    }

    /**
     * 获取已采购产品部门列表
     */
    @Override
    public List<SysDept> getDepts() {
        return baseMapper.getDepts();
    }

    /**
     * 获取已采购数量
     */
    @Override
    public List<PurchaseDetailPo> getPurchaseCountList(IWrapper<Object> wrapper) {
        return baseMapper.getPurchaseCountList(wrapper);
    }

    /**
     * 修改采购状态（采购作废/结束）
     */
    @Override
    public void editPurchaseStatus(PurchaseDto purchaseDto) {
        Assert.notEmpty(purchaseDto.getId(), "采购id不能为空");
        Assert.notEmpty(purchaseDto.getPurchaseStatus(), "采购状态不能为空");
        this.update(q -> q
                .eq(Purchase::getId, purchaseDto.getId())
                .set(Purchase::getPurchaseStatus, purchaseDto.getPurchaseStatus())
                .set(BasePo::getUpdateTime, new Date())
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );
    }

    @Override
    public void purchasePayExcelExport(PurchaseSelectDto dto, HttpServletResponse httpServletResponse) {
        //产品单位字典读取
        Map<String, String> unitDictMap = DictUtils.getDictMap("unit");
        //付款账户字典
        Map<String, String> purchasePaymentAccountMap = DictUtils.getDictMap("purchase_payment_account");

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss");

        List<PayExportExcel> payExportExcelList = new ArrayList<>();

        dto.setPageNum(1);
        dto.setPageSize(-1);
        Page<PurchaseVo> page = getPageByWdly(dto);
        List<PurchaseVo> records = page.getRecords();

        if (ObjectUtils.isEmpty(records)) {
            ExcelUtil.export(httpServletResponse, payExportExcelList, PayExportExcel.class);
        }

        //预处理采购明细信息
        List<Long> purchaseIds = records.stream().map(Purchase::getId).distinct().collect(Collectors.toList());
        List<PurchaseDetail> purchaseDetailLists = purchaseDetailService.list(q -> q.in(PurchaseDetail::getPurchaseId, purchaseIds));
        productInfoService.attributeAssign(purchaseDetailLists, PurchaseDetail::getBussinessId, (item, productInfo) -> {
            //产品编号
            item.setProductCode(productInfo.getCustomCode());
            //产品规格
            item.setProductSpec(productInfo.getSpec());
            //产品单位
            String unit = productInfo.getUnit();
            item.setProductUnit(unitDictMap.getOrDefault(unit, unit));
        });
        Map<Long, List<PurchaseDetail>> purchaseDetailMap = purchaseDetailLists.stream().collect(Collectors.groupingBy(PurchaseDetail::getPurchaseId));

        //赋值数据
        for (PurchaseVo record : records) {
            PayExportExcel payExportExcel = new PayExportExcel();
            //解析采购json
            PurchaseJson purchaseJson = JSONObject.parseObject(record.getVictoriatouristJson(), PurchaseJson.class);

            //采购单号
            payExportExcel.setContractCode(purchaseJson.getContractCode());
            //采购时间
            payExportExcel.setPurchaseTime(record.getCreateTime());
            //采购明细
            List<PurchaseDetail> purchaseDetailList = purchaseDetailMap.get(record.getId());
            //采购金额
            payExportExcel.setAmount(record.getAmount());
            //优惠金额
            payExportExcel.setPreferential(purchaseJson.getPreferential());
            //付款信息
            PurchasePayRecordDetailSelectDto dto1 = new PurchasePayRecordDetailSelectDto();
            dto1.setPurchaseId(record.getId());
            List<PurchasePayRecordDetailVo> purchasePayRecordDetailVos = purchasePayRecordDetailService.getList(dto1);
            //付款账号
            List<String> payAccounts = purchasePayRecordDetailVos.stream().map(PurchasePayRecordDetailVo::getPayAccount).collect(Collectors.toList());
            StringJoiner payAccountsSj = new StringJoiner("\r\n");
            for (String payAccount : payAccounts) {
                payAccountsSj.add(purchasePaymentAccountMap.getOrDefault(payAccount, payAccount));
            }
            payExportExcel.setPayAccount(payAccountsSj.toString());
            //付款金额
            BigDecimal payAmount = purchasePayRecordDetailVos.stream().map(PurchasePayRecordDetail::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            payExportExcel.setPayAmount(payAmount);
            //付款时间
            List<Date> payDates = purchasePayRecordDetailVos.stream().map(PurchasePayRecordDetail::getPayDate).collect(Collectors.toList());
            StringJoiner sj = new StringJoiner("\r\n");
            for (Date payDate : payDates) {
                sj.add(sdf.format(payDate));
            }
            payExportExcel.setPayTime(sj.toString());
            //已入库信息
            PurchaseVo purchaseVo = wdlyService.arrivalDetail(record.getId());
            List<PurchaseDetailVo> purchaseDetailVoList = purchaseVo.getPurchaseDetailVoList();
            Map<Long, PurchaseDetailVo> PurchaseDetailVoMap = purchaseDetailVoList.stream().collect(Collectors.toMap(PurchaseDetailVo::getId, Function.identity()));

            //遍历采购明细
            for (PurchaseDetail purchaseDetail : purchaseDetailList) {
                PayExportExcel newPayExportExcel = BeanUtil.copyProperties(payExportExcel, PayExportExcel.class);

                //产品编号
                newPayExportExcel.setProductCode(purchaseDetail.getProductCode());
                //产品规格
                newPayExportExcel.setProductSpec(purchaseDetail.getProductSpec());
                //产品单位
                newPayExportExcel.setProductUnit(purchaseDetail.getProductUnit());

                //采购数量
                newPayExportExcel.setPurchaseQuantity(purchaseDetail.getCount());
                //采购单价
                newPayExportExcel.setPrice(purchaseDetail.getPrice());
                //到货信息
                PurchaseDetailVo purchaseDetailVo = PurchaseDetailVoMap.get(purchaseDetail.getId());
                //已入库数量
                BigDecimal receiptQuantity = purchaseDetailVo.getReceiptQuantity();
                if (ObjectUtils.isEmpty(receiptQuantity)) {
                    receiptQuantity = BigDecimal.ZERO;
                }
                newPayExportExcel.setReceiptQuantity(receiptQuantity);
                //已质检数量
                BigDecimal qualityQuantity = purchaseDetailVo.getQualityQuantity();
                if (ObjectUtils.isEmpty(qualityQuantity)) {
                    qualityQuantity = BigDecimal.ZERO;
                }
                newPayExportExcel.setQualityQuantity(qualityQuantity);
                //不合格数量
                BigDecimal noQualifiedCount = purchaseDetailVo.getNoQualifiedCount();
                if (ObjectUtils.isEmpty(noQualifiedCount)) {
                    noQualifiedCount = BigDecimal.ZERO;
                }
                newPayExportExcel.setDisqualificationCount(noQualifiedCount);
                //退货数量
                BigDecimal purchaseBackQuantity = purchaseDetailVo.getPurchaseBackQuantity();
                if (ObjectUtils.isEmpty(purchaseBackQuantity)) {
                    purchaseBackQuantity = BigDecimal.ZERO;
                }
                newPayExportExcel.setReturnQuantity(purchaseBackQuantity);
                //退货金额
                newPayExportExcel.setReturnAmount(purchaseBackQuantity.multiply(purchaseDetail.getPrice()));
                //物流单号
                List<DeliverGoodsDetailsPoVo> deliverGoodsDetailList = purchaseDetailVo.getDeliverGoodsDetailList();
                if (ObjectUtils.isNotEmpty(deliverGoodsDetailList)) {
                    String logisticsCode = deliverGoodsDetailList.stream().map(DeliverGoodsDetailsPoVo::getLogisticsCode).collect(Collectors.joining("\r\n"));
                    newPayExportExcel.setLogisticsCode(logisticsCode);
                }

                payExportExcelList.add(newPayExportExcel);
            }

        }
        try {
            File file = new File("C:\\Users\\ASUS\\Desktop\\ou.xlsx");
            FileOutputStream fos = new FileOutputStream(file);
            EasyExcel.write(fos, PayExportExcel.class).sheet("aa").doWrite(payExportExcelList);
        }catch (Exception e){
            e.printStackTrace();
        }

        ExcelUtil.export(httpServletResponse, payExportExcelList, PayExportExcel.class);
    }
}
