package com.fjhx.stock.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.base.Condition;
import com.fjhx.constants.StatusConstant;
import com.fjhx.entity.stock.StockDetail;
import com.fjhx.entity.stock.StockTag;
import com.fjhx.entity.stock.StockWater;
import com.fjhx.entity.stock.StockWaterdetial;
import com.fjhx.stock.mapper.StockWaterMapper;
import com.fjhx.stock.service.StockDetailService;
import com.fjhx.stock.service.StockTagService;
import com.fjhx.stock.service.StockWaterService;
import com.fjhx.stock.service.StockWaterdetialService;
import com.fjhx.utils.Assert;
import com.fjhx.utils.BigDecimalUtil;
import com.fjhx.utils.WrapperUtil;
import com.fjhx.utils.wrapperUtil.IWrapper;
import com.fjhx.utils.wrapperUtil.KeywordData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * <p>
 * 出入库 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2022-07-04
 */
@Service
public class StockWaterServiceImpl extends ServiceImpl<StockWaterMapper, StockWater> implements StockWaterService {

    @Autowired
    private StockWaterdetialService stockWaterdetialService;

    @Autowired
    private StockDetailService stockDetailService;

    @Autowired
    private StockTagService stockTagService;

    @Override
    public Map<String, Object> getPickingStatistics(Map<String, String> condition) {

        QueryWrapper<?> wrapper = WrapperUtil.init(condition)
                // 时间段查询
                .periodOfTime("sw.CreatedTime")
                .getWrapper();
        wrapper.eq("sw.IsDelete", 0);
        wrapper.in("sw.StockChangeType", 15, 20, 23);

        // 获取统计数据
        List<Map<String, Object>> pickingStatistics = baseMapper.getPickingStatistics(wrapper);

        HashMap<String, Object> result = new HashMap<>();

        // 按物料属性分组
        Map<String, List<Map<String, Object>>> groupByStatistics = pickingStatistics.stream().collect(
                Collectors.groupingBy(item -> item.get("materialType").toString()));

        // 统计面料
        HashMap<String, Object> fabricStatistics = new HashMap<>();
        fabricStatistics.put("total", 0);
        fabricStatistics.put("length", BigDecimal.ZERO);
        fabricStatistics.put("measureArea", BigDecimal.ZERO);
        fabricStatistics.put("money", BigDecimal.ZERO);

        // 面料属性属性
        List<Map<String, Object>> fabricTree = new ArrayList<>();

        // 构建前端所需参数
        for (Map.Entry<String, List<Map<String, Object>>> entry : groupByStatistics.entrySet()) {
            String key = entry.getKey();
            List<Map<String, Object>> value = entry.getValue();

            // 墨水统计
            if (key.equals("3")) {
                // 墨水统计
                HashMap<Object, Object> inkStatistics = new HashMap<>();
                // 件数
                inkStatistics.put("total", value.size());
                // 公斤
                inkStatistics.put("weight", value.stream().map(item -> (BigDecimal) item.get("changeNum"))
                        .reduce(BigDecimal.ZERO, BigDecimal::add));
                // 金额
                inkStatistics.put("money", value.stream()
                        .map(item -> ((BigDecimal) item.get("changeNum")).multiply((BigDecimal) item.get("materialPrice")))
                        .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP));

                result.put("inkStatistics", inkStatistics);

                // 墨水领料明细
                List<HashMap<String, Object>> inkDetails = new ArrayList<>(value.stream().collect(Collectors.toMap(
                        item -> item.get("userId").toString(), // 根据用户id分组
                        item -> { // 统计单条数据
                            HashMap<String, Object> map = new HashMap<>();
                            map.put("userId", item.get("userId"));
                            map.put("userName", item.get("userName"));
                            map.put("total", 1);
                            map.put("weight", item.get("changeNum"));
                            map.put("money", ((BigDecimal) item.get("changeNum"))
                                    .multiply((BigDecimal) item.get("materialPrice")).setScale(2, RoundingMode.HALF_UP));
                            return map;
                        },
                        (v1, v2) -> { // 当有多条用户记录时，统计数据
                            v1.put("total", ((Integer) v1.get("total")) + 1);
                            v1.put("weight", ((BigDecimal) v1.get("weight")).add((BigDecimal) v2.get("weight")));
                            v1.put("money", ((BigDecimal) v1.get("money")).add((BigDecimal) v2.get("money")));
                            return v1;
                        })).values());

                result.put("inkDetails", inkDetails);
            }
            // 面料统计
            else {
                // 卷数
                int size = value.size();
                // 米数
                BigDecimal length = value.stream().map(item -> (BigDecimal) item.get("changeNum")).reduce(BigDecimal.ZERO, BigDecimal::add);
                // 面积
                BigDecimal measureArea = value.stream().map(item -> ((BigDecimal) item.get("changeNum"))
                                .multiply(BigDecimal.valueOf((float) item.get("materialWidth")))
                                .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP))
                        .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);
                // 金额
                BigDecimal money = value.stream().map(item -> ((BigDecimal) item.get("changeNum")).multiply((BigDecimal) item.get("materialPrice")))
                        .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);

                // 添加到面料统计
                fabricStatistics.put("total", (Integer) fabricStatistics.get("total") + size);
                fabricStatistics.put("length", ((BigDecimal) fabricStatistics.get("length")).add(length));
                fabricStatistics.put("measureArea", ((BigDecimal) fabricStatistics.get("measureArea")).add(measureArea));
                fabricStatistics.put("money", ((BigDecimal) fabricStatistics.get("money")).add(money));

                // 构建树形
                Map<String, Object> attribute = new HashMap<>();
                attribute.put("materialType", key);
                attribute.put("total", size);
                attribute.put("length", length);
                attribute.put("measureArea", measureArea);
                attribute.put("money", money);
                attribute.put("name",
                        key.equals("0") ? "直喷" : key.equals("1") ? "热转" : key.equals("2") ? "打纸" : "其他");

                // 查询子集
                List<HashMap<String, Object>> children = new ArrayList<>(value.stream().collect(Collectors.toMap(
                        item -> item.get("userId").toString(), // 根据用户id分组
                        item -> { // 统计单条数据
                            HashMap<String, Object> map = new HashMap<>();
                            map.put("userId", item.get("userId"));
                            map.put("name", item.get("userName"));
                            map.put("total", 1); // 数量
                            map.put("length", item.get("changeNum")); // 米数

                            // 面积
                            map.put("measureArea", ((BigDecimal) item.get("changeNum"))
                                    .multiply(BigDecimal.valueOf((float) item.get("materialWidth")))
                                    .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP)); // 面积
                            // 金额
                            map.put("money", ((BigDecimal) item.get("changeNum")).multiply((BigDecimal) item.get("materialPrice"))
                                    .setScale(2, RoundingMode.HALF_UP));
                            return map;
                        },
                        (v1, v2) -> { // 当有多条用户记录时，统计数据
                            v1.put("total", ((Integer) v1.get("total")) + 1);
                            v1.put("length", ((BigDecimal) v1.get("length")).add((BigDecimal) v2.get("length")));
                            v1.put("measureArea", ((BigDecimal) v1.get("measureArea")).add((BigDecimal) v2.get("measureArea")));
                            v1.put("money", ((BigDecimal) v1.get("money")).add((BigDecimal) v2.get("money")));
                            return v1;
                        })).values());

                attribute.put("children", children);

                fabricTree.add(attribute);
            }
        }

        // 面料统计
        result.put("fabricStatistics", fabricStatistics);

        // 面料树形
        result.put("fabricTree", fabricTree);

        return result;
    }

    @Override
    public Map<String, Integer> getPickingStockChangeTypeCount(Map<String, String> condition) {
        QueryWrapper<?> wrapper = createPickingWrapper(condition);

        return baseMapper.getPickingStockChangeTypeCount(wrapper);
    }

    @Override
    public Page<Map<String, Object>> getPickingPage(Map<String, String> condition) {

        QueryWrapper<?> wrapper = createPickingWrapper(condition);

        // 出入库类型
        String type = condition.get("type");
        if (ObjectUtil.isEmpty(type) || type.equals("0")) {
            wrapper.in("sw.StockChangeType", 15, 20, 23);
        } else {
            wrapper.eq("sw.StockChangeType", type);
        }

        return baseMapper.getPickingPage(createPage(condition), wrapper);
    }

    @Override
    public Map<String, Object> contractPaymentStatistics(Map<String, String> condition) {
        QueryWrapper<?> wrapper = WrapperUtil.init(condition).periodOfTime("pc.ApprovalTime").getWrapper();
        wrapper.eq("pc.IsDelete", 0);
        wrapper.in("s.AccountDate ", 45, 30, 15, 0);

        List<Map<String, Object>> list = baseMapper.contractPaymentStatistics(wrapper);


        Map<String, Object> result = new HashMap<>();

        /*
            0 =》申购金额
            1 =》面料采购
            2 =》墨水采购
            3 =》其他
         */
        Map<String, BigDecimal> collect = list.stream().collect(Collectors.toMap(
                item -> {
                    String materialType = item.get("materialType").toString();
                    switch (materialType) {
                        case "3":
                            return "2";
                        case "4":
                            return "3";
                        default:
                            return "1";
                    }
                },
                item -> ((BigDecimal) item.get("money")).setScale(2, RoundingMode.HALF_UP),
                BigDecimal::add
        ));
        collect.putIfAbsent("1", BigDecimal.ZERO);
        collect.putIfAbsent("2", BigDecimal.ZERO);
        collect.putIfAbsent("3", BigDecimal.ZERO);
        collect.put("0", collect.get("1").add(collect.get("2")).add(collect.get("3")));

         /*
            4 =》45天账期
            5 =》30天账期
            6 =》15天账期
            7 =》预付款
         */
        Map<String, BigDecimal> collect2 = list.stream().collect(Collectors.toMap(
                item -> {
                    Integer accountDate = (Integer) item.get("accountDate");
                    switch (accountDate) {
                        case 45:
                            return "4";
                        case 30:
                            return "5";
                        case 15:
                            return "6";
                        default:
                            return "7";
                    }
                },
                item -> ((BigDecimal) item.get("money")).setScale(2, RoundingMode.HALF_UP),
                BigDecimal::add
        ));
        collect.putIfAbsent("4", BigDecimal.ZERO);
        collect.putIfAbsent("5", BigDecimal.ZERO);
        collect.putIfAbsent("6", BigDecimal.ZERO);
        collect.putIfAbsent("7", BigDecimal.ZERO);

        collect.putAll(collect2);

        // 赋值全部金额查询信息
        result.put("money", collect);


        // 根据供应商id，统计出向每家公司付款的金额
        List<Map<String, Object>> values = list.stream().collect(Collectors.toMap(
                        item -> item.get("supplierId").toString(),
                        item -> {
                            Map<String, Object> map = new HashMap<>();
                            map.put("supplierId", item.get("supplierId"));
                            map.put("supplierName", item.get("supplierName"));
                            map.put("money", ((BigDecimal) item.get("money")).setScale(2, RoundingMode.HALF_UP));
                            return map;
                        },
                        (v1, v2) -> {
                            v1.put("money", ((BigDecimal) v1.get("money")).add((BigDecimal) v2.get("money")));
                            return v1;
                        }
                )).values().stream()
                .sorted(Comparator.comparing((Map<String, Object> v) -> ((BigDecimal) v.get("money"))).reversed())
                .collect(Collectors.toList());

        /*
         0 全部公司统计
         1 50万以上
         2 20~50万
         3 10~20万
         4 5~20万
         5 5万以下
         */
        Map<String, List<Map<String, Object>>> map = values.stream()

                .collect(Collectors.groupingBy(item -> {
                    BigDecimal money = (BigDecimal) item.get("money");
                    if (money.compareTo(new BigDecimal("50000")) < 0) {
                        return "5";
                    }
                    if (money.compareTo(new BigDecimal("100000")) < 0) {
                        return "4";
                    }
                    if (money.compareTo(new BigDecimal("200000")) < 0) {
                        return "3";
                    }
                    if (money.compareTo(new BigDecimal("500000")) < 0) {
                        return "2";
                    }
                    return "1";
                }));

        map.put("0", values);
        map.putIfAbsent("1", new ArrayList<>());
        map.putIfAbsent("2", new ArrayList<>());
        map.putIfAbsent("3", new ArrayList<>());
        map.putIfAbsent("4", new ArrayList<>());
        map.putIfAbsent("5", new ArrayList<>());

        result.put("statisticsSupplier", map);

        return result;
    }

    @Override
    public Page<Map<String, Object>> subscriptionAmountPage(Map<String, String> condition) {

        QueryWrapper<?> wrapper = WrapperUtil
                .init(condition)
                .periodOfTime("pc.ApprovalTime")
                .in("pc.SupplierId", "supplierIdList")
                .getWrapper();

        wrapper.eq("pc.IsDelete", 0);

        Page<Map<String, Object>> result = baseMapper.subscriptionAmountPage(createPage(condition), wrapper);
        List<Map<String, Object>> records = result.getRecords();

        // 格式转换
        records.forEach(item -> {
            item.put("purchaseQty", ((BigDecimal) item.get("purchaseQty")).setScale(2, RoundingMode.HALF_UP));
            item.put("totalAmount", ((BigDecimal) item.get("totalAmount")).setScale(2, RoundingMode.HALF_UP));
            item.put("adjustAmount", item.get("adjustAmount") == null ? "-" : ((BigDecimal) item.get("adjustAmount")).setScale(2, RoundingMode.HALF_UP));
            item.put("approvalTime", DateUtil.format((Date) item.get("approvalTime"), "yyyy-MM-dd"));
        });

        return result;
    }

    @Override
    public Map<String, Object> remainingToday(Map<String, String> condition) {

        List<Map<String, Object>> list = baseMapper.remainingToday();

        Map<String, Map<String, Object>> Statistics = list.stream()
                .collect(Collectors.toMap(
                        item -> item.get("materialType").toString().equals("3") ? "ink" : "fabric",
                        this::remainingTodayGetMap,
                        this::remainingTodayMerge
                ));

        HashMap<String, Object> absentInk = new HashMap<>();
        absentInk.put("count", 0);
        absentInk.put("sum", BigDecimal.ZERO);
        absentInk.put("measureArea", BigDecimal.ZERO);
        absentInk.put("money", BigDecimal.ZERO);
        Statistics.putIfAbsent("ink", absentInk);

        HashMap<String, Object> absentFabric = new HashMap<>();
        absentInk.put("count", 0);
        absentInk.put("sum", BigDecimal.ZERO);
        absentInk.put("money", BigDecimal.ZERO);
        Statistics.putIfAbsent("fabric", absentFabric);

        HashMap<String, Object> result = new HashMap<>(Statistics);

        Map<String, Map<String, Object>> typeStatistics = list.stream()
                .filter(item -> !item.get("materialType").toString().equals("3")) // 过滤出墨水不统计
                .collect(Collectors.toMap(
                        item -> item.get("materialType").toString(),
                        this::remainingTodayGetMap,
                        this::remainingTodayMerge
                ));

        result.put("typeStatistics", typeStatistics);


        Map<String, Map<String, Object>> purposeStatistics = list.stream()
                .filter(item -> !item.get("materialType").toString().equals("3")) // 过滤出墨水不统计
                .collect(Collectors.toMap(
                        item -> item.get("materialPurpose").toString(),
                        item -> {
                            Map<String, Object> map = remainingTodayGetMap(item);
                            map.put("materialPurpose", item.get("materialPurpose"));
                            return map;
                        },
                        this::remainingTodayMerge
                ));

        result.put("purposeStatistics", purposeStatistics.values().stream()
                .sorted((v1, v2) -> ((BigDecimal) v2.get("measureArea")).compareTo((BigDecimal) v1.get("measureArea")))
                .collect(Collectors.toList()));

        return result;
    }

    @Override
    public Page<Map<String, Object>> remainingTodayPage(Map<String, String> condition) {

        QueryWrapper<?> wrapper = createRemainingTodayWrapper(condition);

        // 查询基本信息
        Page<Map<String, Object>> page = baseMapper.remainingTodayPage(createPage(condition), wrapper);

        List<Map<String, Object>> records = page.getRecords();
        if (records.size() == 0) {
            return page;
        }

        List<String> materialIdList = records.stream().map(item -> item.get("materialId").toString()).collect(Collectors.toList());

        // 查库存所在信息
        List<Map<String, Object>> materialHouseList = baseMapper.selectMaterialHouse(
                Wrappers.query().in("m.id", materialIdList).eq("sd.IsDelete", 0).groupBy("m.id,sh.id"));

        // 按物料id分组
        Map<String, List<Map<String, Object>>> materialIdGroup =
                materialHouseList.stream().collect(Collectors.groupingBy(item -> item.get("materialId").toString()));

        records.forEach(item -> {
            String materialId = item.get("materialId").toString();
            // 赋值物料所在库存信息
            item.put("houseInfo", materialIdGroup.get(materialId));
        });

        return page;
    }

    @Override
    public List<Map<String, Object>> remainingTodayList(Map<String, String> condition) {
        QueryWrapper<?> wrapper = createRemainingTodayWrapper(condition);

        // 查询基本信息
        List<Map<String, Object>> list = baseMapper.remainingTodayList(wrapper);
        if (list.size() == 0) {
            return list;
        }

        Map<String, Map<String, Object>> materialCodeMap = list.stream().collect(Collectors.toMap(
                item -> item.get("materialCode").toString(),
                item -> item
        ));


        QueryWrapper<Object> query = Wrappers.query();
        query.in("sd.MaterialCode", materialCodeMap.keySet());
        query.eq("st.IsDelete", 0);
        query.orderByAsc("sd.MaterialCode", "sd.CreatedTime");
        List<Map<String, Object>> inStockList = baseMapper.inStockList(query);

        if (inStockList.size() == 0) {
            return inStockList;
        }

        Date date = new Date();

        inStockList.forEach(item -> {

            Date createTime = (Date) item.get("createTime");
            item.put("createTime", DateUtil.format(createTime, "yyyy-MM-dd"));
            item.put("inStockTime", DateUtil.betweenDay(date, createTime, true));

            Map<String, Object> map = materialCodeMap.get(item.get("materialCode").toString());
            if (map != null) {
                item.putAll(map);
            }
        });

        return inStockList;
    }

    @Override
    public List<Map<String, Object>> inStockList(Map<String, String> condition) {
        String materialCode = condition.get("materialCode");
        Assert.notEmpty(materialCode, "物料编码不能为空");

        QueryWrapper<Object> wrapper = Wrappers.query();
        wrapper.eq("sd.MaterialCode", materialCode);
//        wrapper.eq("st.IsDelete", 0);
        wrapper.orderByAsc("sd.CreatedTime");


        List<Map<String, Object>> list = baseMapper.inStockList(wrapper);

        if (list.size() == 0) {
            return list;
        }

        Date date = new Date();

        for (Map<String, Object> map : list) {
            Date createTime = (Date) map.get("createTime");
            map.put("createTime", DateUtil.format(createTime, "yyyy-MM-dd"));
            map.put("inStockTime", DateUtil.betweenDay(date, createTime, true));
        }

        return list;
    }

    @Override
    public Page<Map<String, Object>> receiptSequence(Map<String, String> condition) {

        String date = condition.get("date");
        Assert.notEmpty(date, "时间不能为空");
        DateTime parse = DateUtil.parse(date, "yyyy-MM");
        condition.put("beginTime", DateUtil.beginOfMonth(parse).toString("yyyy-MM-dd HH:mm:ss"));
        condition.put("endTime", DateUtil.endOfMonth(parse).toString("yyyy-MM-dd HH:mm:ss"));

        return baseMapper.receiptSequence(createPage(condition), condition);
    }

    @Override
    public List<Map<String, Object>> contractPaymentList(Map<String, String> condition) {
        String balancePurBillNo = condition.get("balancePurBillNo");
        return baseMapper.contractPaymentList(balancePurBillNo);
    }

    @Override
    public List<Map<String, Object>> receiptList(Map<String, String> condition) {
        String purchaseBillNo = condition.get("purchaseBillNo");
        return baseMapper.receiptList(purchaseBillNo);
    }

    @Override
    public List<JSONObject> issue(Condition condition) {
        Date date = condition.getDate("date");
        String account = condition.getStr("account", "账号不能为空");

        List<Map<String, Object>> list = baseMapper.getWater(Wrappers.query()
                .between("swd.CreatedTime", date, DateUtil.offsetDay(date, 1))
                .in("swd.StockChangeType", 20, 23)
                .eq("aa.AccountNo", account)
                .likeRight("m.Code", "01.")
        );

        return format(list);
    }

    @Override
    public List<JSONObject> materialReturn(Condition condition) {
        Date date = condition.getDate("date");
        String account = condition.getStr("account", "账号不能为空");

        List<Map<String, Object>> list = baseMapper.getMaterialReturn(Wrappers.query()
                .between("sb.checker_time", date, DateUtil.offsetDay(date, 1))
                .eq("sb.operator_id", account)
                .likeRight("m.Code", "01."));

        return format(list);
    }

    @Override
    public List<JSONObject> transferIn(Condition condition) {
        Date date = condition.getDate("date");
        String account = condition.getStr("account", "账号不能为空");

        List<Map<String, Object>> list = baseMapper.getTransferPickingList(Wrappers.query()
                .between("st.submit_time", date, DateUtil.offsetDay(date, 1))
                .eq("st.status", StatusConstant.YES)
                .eq("st.del_flag", 0)
                .eq("aa.AccountNo", account)
        );

        return format(list);
    }

    @Override
    public List<JSONObject> transferOut(Condition condition) {
        Date date = condition.getDate("date");
        String account = condition.getStr("account", "账号不能为空");

        List<Map<String, Object>> list = baseMapper.getTransferBackList(Wrappers.query()
                .between("st.submit_time", date, DateUtil.offsetDay(date, 1))
                .eq("st.status", StatusConstant.YES)
                .eq("st.del_flag", 0)
                .eq("st.submit_user", account)
        );

        return format(list);
    }

    @Override
    public List<Map<String, Object>> inventoryDetails(Condition condition) {

        return baseMapper.getInventoryDetails(condition);
    }

    @Override
    public Page<Map<String, Object>> outPage(Condition condition) {

        Page<Map<String, Object>> page = baseMapper.outPage(condition.getPage(), getWrapper(condition));

        List<Map<String, Object>> records = page.getRecords();
        if (records.size() == 0) {
            return page;
        }

        // 查询出库明细
        List<String> waterIdList = records.stream().map(item -> Convert.toStr(item.get("waterId"))).collect(Collectors.toList());

        Map<String, List<StockWaterdetial>> waterIdGroup = stockWaterdetialService.getKGroup(
                StockWaterdetial::getWaterId,
                q -> q.in(StockWaterdetial::getWaterId, waterIdList)
                        .select(StockWaterdetial::getWaterId, StockWaterdetial::getChangeNum, StockWaterdetial::getRfidCode)
                        .eq(StockWaterdetial::getIsDelete, 0));

        records.forEach(item -> {
            String waterId = Convert.toStr(item.get("waterId"), "");
            item.put("detailsList", waterIdGroup.get(waterId));
        });

        return page;
    }

    @Override
    public Map<String, Object> outStatistics(Condition condition) {
        return baseMapper.outStatistics(getWrapper(condition));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void swap(Condition condition) {
        String oldRfid = condition.getStr("oldRfid");
        String newRfid = condition.getStr("newRfid");

        StockDetail stockDetail = stockDetailService.getOne(
                q -> q.eq(StockDetail::getIsdelete, 0).eq(StockDetail::getRfidcode, oldRfid));

        if (stockDetail != null) {
            stockDetailService.removeById(stockDetail);

            stockDetail.setId(null);
            stockDetail.setRfidcode(newRfid);
            stockDetailService.save(stockDetail);
        }

        StockTag stockTag = stockTagService.getOne(
                q -> q.eq(StockTag::getIsDelete, 0).eq(StockTag::getRfidCode, oldRfid));

        if (stockTag != null) {
            stockTagService.removeById(stockTag);

            stockTag.setId(null);
            stockTag.setRfidCode(newRfid);
            stockTagService.save(stockTag);
        }
    }

    private IWrapper<Object> getWrapper(Condition condition) {

        String beginTime = condition.getStr("beginTime");
        String endTime = condition.getStr("endTime");

        IWrapper<Object> wrapper = IWrapper.getWrapper(condition);
        wrapper.eq("sw.IsDelete", 0)
                .func(q -> {
                    Integer stockChangeType = condition.getInt("stockChangeType");
                    if (ObjectUtil.isEmpty(stockChangeType)) {
                        q.in("sw.StockChangeType", 20, 23, 26, 27);
                    } else {
                        // if (stockChangeType == 20) {
                        //     q.in("sw.StockChangeType", 20, 23);
                        // } else {
                        //     q.eq("sw.StockChangeType", stockChangeType);
                        // }
                        q.eq("sw.StockChangeType", stockChangeType);
                    }
                })
                .keyword(new KeywordData("m.name"), new KeywordData("m.code"))
                .eq("sw.OperUserId", condition.getStr("operUserId"))
                .between(ObjectUtil.isAllNotEmpty(beginTime, endTime), "sw.CreatedTime", beginTime, endTime)
                .orderByDesc("sw.CreatedTime");
        return wrapper;
    }

    private List<JSONObject> format(List<Map<String, Object>> list) {
        Map<String, JSONObject> collect = list.stream().collect(Collectors.toMap(
                item -> item.get("materialCode").toString(),
                item -> {
                    Object changeNum = item.get("changeNum");

                    JSONObject map = new JSONObject();
                    map.put("receiveUser", item.get("receiveUser"));
                    map.put("submitUser", item.get("submitUser"));

                    map.put("materialCode", item.get("materialCode"));
                    map.put("materialName", item.get("materialName"));
                    map.put("count", 1);
                    map.put("quantity", changeNum);
                    map.put("area", BigDecimalUtil.init(changeNum)
                            .multiply(item.get("width")).divideTry(100, 2).getValue());

                    JSONObject materialMap = new JSONObject();
                    materialMap.put("quantity", changeNum);
                    materialMap.put("rfid", item.get("rfid"));
                    map.put("materialList", Collections.singletonList(materialMap));

                    return map;
                },
                (v1, v2) -> {
                    v1.put("count", v1.getInteger("count") + v2.getInteger("count"));
                    v1.put("quantity", v1.getBigDecimal("quantity").add(v2.getBigDecimal("quantity")));
                    v1.put("area", v1.getBigDecimal("area").add(v2.getBigDecimal("area")));

                    List<JSONObject> newList = new ArrayList<>();
                    newList.addAll((List<JSONObject>) v1.get("materialList"));
                    newList.addAll((List<JSONObject>) v2.get("materialList"));

                    v1.put("materialList", newList);
                    return v1;
                }
        ));

        return new ArrayList<>(collect.values());
    }


    private QueryWrapper<?> createRemainingTodayWrapper(Map<String, String> condition) {
        QueryWrapper<?> wrapper = WrapperUtil.init(condition)
                .keyword("m.Code", "m.Name") // 关键字查询
                .eq("m.CategoryCode", "categoryCode") // 物料分类
                .getWrapper();

        wrapper.eq("m.IsDelete", 0);

        // 01.
        // 03.008.
        wrapper.and(q -> q.likeRight("m.code", "01.").or().likeRight("m.code", "03.008."));


        String inventoryResults = condition.get("inventoryResults");
        if ("0".equals(inventoryResults)) {
            wrapper.eq("if(a.MaterialCode is null, 1, IF(a.CheckTagCount = a.TagQuantity AND a.CheckTagCount = a.HandTagCount, 1, 0))", inventoryResults);
        }

        // 物料分组
        wrapper.groupBy("m.id");
        // 在库
//        wrapper.eq("sd.IsDelete", 0);

        // 仓库id
        String houseId = condition.get("houseId");
        if (ObjectUtil.isNotEmpty(houseId)) {
            List<String> materialCodeList = baseMapper.selectMaterialIdByHouseId(houseId);
            wrapper.in("m.code", materialCodeList);
        }

        // 工艺类型
        String technologyType = condition.get("technologyType");
        if (ObjectUtil.isNotEmpty(technologyType)) {
            if (technologyType.equals("5")) {
                wrapper.in("m.TechnologyType", 0, 1, 2, 4);
            } else {
                wrapper.eq("m.TechnologyType", technologyType);
            }
        }

        // 用途
        String purpose = condition.get("purpose");
        if (ObjectUtil.isNotEmpty(purpose)) {
            if (purpose.equals("其他")) {
                wrapper.ne("m.TechnologyType", 3);
                wrapper.eq("ifNull(m.Purpose,'其他')", purpose);
            } else {
                wrapper.eq("m.Purpose", purpose);
            }
        }
        return wrapper;
    }

    private QueryWrapper<?> createPickingWrapper(Map<String, String> condition) {
        QueryWrapper<?> wrapper = WrapperUtil.init(condition)
                .periodOfTime("sw.CreatedTime") // 时间段查询
                .eq("m.TechnologyType", "materialType") // 物料属性
                .eq("sw.OperUserId", "userId") // 用户
                .getWrapper();

        wrapper.eq("sw.IsDelete", 0); // 未删除

        return wrapper;
    }

    private Map<String, Object> remainingTodayGetMap(Map<String, Object> item) {
        BigDecimal quantity = (BigDecimal) item.get("quantity");
        Map<String, Object> map = new HashMap<>();
        map.put("count", 1);
        map.put("sum", quantity.setScale(2, RoundingMode.HALF_UP));
        if (!item.get("materialType").toString().equals("3")) {
            map.put("measureArea", quantity.multiply(BigDecimal.valueOf((float) item.get("materialWidth"))).setScale(2, RoundingMode.HALF_UP));
        }
        map.put("money", quantity.multiply((BigDecimal) item.get("price")).setScale(2, RoundingMode.HALF_UP));
        return map;
    }

    private Map<String, Object> remainingTodayMerge(Map<String, Object> v1, Map<String, Object> v2) {
        v1.put("count", (Integer) v1.get("count") + 1);
        v1.put("sum", ((BigDecimal) v1.get("sum")).add((BigDecimal) v2.get("sum")));
        Object measureArea = v1.get("measureArea");
        if (measureArea != null) {
            v1.put("measureArea", ((BigDecimal) measureArea).add((BigDecimal) v2.get("measureArea")));
        }
        v1.put("money", ((BigDecimal) v1.get("money")).add((BigDecimal) v2.get("money")));
        return v1;
    }

}
