package com.sunda.spmswms.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunda.spmscommon.ResponseResult;
import com.sunda.spmswms.dto.WhsSearchDTO;
import com.sunda.spmswms.entity.InventoryCheckAction;
import com.sunda.spmswms.entity.WhsStorage;
import com.sunda.spmswms.entity.WhsStorageInventory;
import com.sunda.spmswms.mapper.WhsInventoryInfoMapper;
import com.sunda.spmswms.mapper.WhsStorageInventoryMapper;
import com.sunda.spmswms.service.*;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

import static com.sunda.spmscommon.Constans.*;

/**
 * <p>
 * 储位库存信息表 服务实现类
 * </p>
 *
 * @author Wayne
 * @since 2021-03-18
 */
@Service
public class WhsStorageInventoryServiceImpl extends ServiceImpl<WhsStorageInventoryMapper, WhsStorageInventory>
        implements IWhsStorageInventoryService {

    @Autowired
    WhsStorageInventoryMapper whsStorageInventoryMapper;
    @Autowired
    IWhsOperateLogService iWhsOperateLogService;
    @Autowired
    WhsInventoryInfoMapper whsInventoryInfoMapper;
    @Autowired
    IWhsStorageService iWhsStorageService;
    @Autowired
    IWhsInventoryInfoService iWhsInventoryInfoService;

    @Autowired
    ISapBoxNoteService iSapBoxNoteService;

    /* 根据日期获取最近有出入库的贸易货储位库存 */
    @Override
    public ResponseResult getStorageMByDate(String werks, String whsLocationCode, String startDate, String endDate) {
        return ResponseResult.success().add("storageInventory",
                this.baseMapper.getStorageMByDate(werks, whsLocationCode, startDate, endDate));
    }

    /* 根据日期获取最近有出入库的储位库存(海外仓适用) */
    @Override
    public ResponseResult getStorageByDate(String werks, String whsLocationCode, String startDate, String endDate,String documentType) {
        return ResponseResult.success().add("storageInventory",
                this.baseMapper.getStorageByDate(werks, whsLocationCode, startDate, endDate,documentType));
    }

    /* 根据日期获取最近有出入库的备件货储位库存 */
    @Override
    public ResponseResult getStorageXByDate(String werks, String whsLocationCode, String startDate, String endDate) {
        return ResponseResult.success().add("storageInventory",
                this.baseMapper.getStorageXByDate(werks, whsLocationCode, startDate, endDate));
    }

    /**
     * export = 1 表示请求数据导出所有数据到报表中；export = 0 表示仅供 web 端查询，返回分页数据；
     */
    @Override
    public ResponseResult getWhsList(List<String> werks, List<String> whsLocationCode, List<String> storageArea,
            List<String> shelfNo, List<String> shelfLayer, List<String> shelfCell, List<String> storageNo,
            List<String> materialNo, String storageCategory, List<String> boxNote, int pageNo,
            int pageSize) {

        Page<Map<String, Object>> pages = new Page<>(pageNo, pageSize);
        List<Map<String, Object>> pageData = new ArrayList<>();
        if ("M".equals(storageCategory)) {
            pageData = whsStorageInventoryMapper.getWhsStorageInventoryMPage(pages, werks, whsLocationCode, storageArea,
                    shelfNo, shelfLayer, shelfCell, storageNo, materialNo);
        } else if ("X".equals(storageCategory)) {
            pageData = whsStorageInventoryMapper.getWhsStorageInventoryXPage(pages, werks, whsLocationCode, storageArea,
                    shelfNo, shelfLayer, shelfCell, storageNo, boxNote);
        } else {
            pageData = whsStorageInventoryMapper.getWhsStorageInventoryPage(pages, werks, whsLocationCode, storageArea,
                    shelfNo, shelfLayer, shelfCell, storageNo, materialNo, boxNote);
        }
        pages.setRecords(pageData);
        return ResponseResult.success().add("storageInventory", pages);
    }

    /**
     * 不分页 ；
     */
    @Override
    public ResponseResult getWhsStorageInventory(List<String> werks, List<String> whsLocationCode,
            List<String> storageArea, List<String> shelfNo, List<String> shelfLayer, List<String> shelfCell,
            List<String> storageNo, List<String> materialNo, String storageCategory, List<String> boxNote, String searchInfo, String packageNote) {

        List<Map<String, Object>> marmList = new ArrayList<Map<String, Object>>();
        if(materialNo!=null && materialNo.size()>0){
            marmList = whsStorageInventoryMapper.getMaterialMarmByNo(materialNo);
        }

        //storageCategory ="02";
        if ("02".equals(storageCategory)) {//查旧件的储位
            return ResponseResult.success().add("storageInventory", whsStorageInventoryMapper.getWhsStorageInventoryOld(
                    werks, whsLocationCode, storageArea, shelfNo, shelfLayer, shelfCell, storageNo, materialNo)).add("marmList",marmList);
        }else if ("M".equals(storageCategory)) {
            return ResponseResult.success().add("storageInventory", whsStorageInventoryMapper.getWhsStorageInventoryM(
                    werks, whsLocationCode, storageArea, shelfNo, shelfLayer, shelfCell, storageNo, materialNo)).add("marmList",marmList);
        } else if ("X".equals(storageCategory)) {
            return ResponseResult.success().add("storageInventory", whsStorageInventoryMapper.getWhsStorageInventoryX(
                    werks, whsLocationCode, storageArea, shelfNo, shelfLayer, shelfCell, storageNo, boxNote, packageNote)).add("marmList",marmList);
        } else {
            return ResponseResult.success().add("storageInventory",
                    whsStorageInventoryMapper.getWhsStorageInventory(werks, whsLocationCode, storageArea, shelfNo,
                            shelfLayer, shelfCell, storageNo, materialNo, boxNote, searchInfo)).add("marmList",marmList);
        }

    }

    /* 更新储位库存，备件货,上架 */
    @Override
    public ResponseResult updateStorageInventoryX(String uuid, String boxNote, String deliveryNoteSap, String userId) {
        try {
            QueryWrapper<WhsStorageInventory> wrapper = new QueryWrapper<WhsStorageInventory>().eq("BOX_NOTE", boxNote);
            WhsStorageInventory storageInventory = whsStorageInventoryMapper.selectOne(wrapper);
            if (storageInventory != null) {
                // 如果箱码已经存在，则报错
                return ResponseResult.error("Error, the box note alreay exist in other storage location");
            } else {
                WhsStorageInventory whsStorageInventory = new WhsStorageInventory();
                whsStorageInventory.setUuid(uuid);
                whsStorageInventory.setBoxNote(boxNote);
                whsStorageInventory.setQuantity(1.0);
                whsStorageInventory.setAvailableQty(1.0);
                /** 物料在对应储位不存在数据，则新建一条 储位-物料-数量 的数据； */
                whsStorageInventoryMapper.insert(whsStorageInventory);
                WhsStorage whsStorage = iWhsStorageService.getWhsStorageByUuid(uuid);
                iWhsOperateLogService.insertWhsOperateLogBS(uuid, boxNote, 1.0, deliveryNoteSap,
                        SPARE_PARTS_INTO_STORAGE, userId, whsStorage.getWerks(), whsStorage.getWhsLocationCode());
            }

            return ResponseResult.success();
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("Error when update storage Inventory X");
        }
    }

    @Override
    public ResponseResult insertStorageInventoryX(String uuid, String boxNote, String deliveryNoteSap, String userId) {
        try {
            QueryWrapper<WhsStorageInventory> wrapper = new QueryWrapper<WhsStorageInventory>().eq("BOX_NOTE", boxNote);
            WhsStorageInventory storageInventory = whsStorageInventoryMapper.selectOne(wrapper);
            if (storageInventory != null) {
                // 如果箱码已经存在，则报错
                return ResponseResult.error("Error, the box note alreay exist in other storage location");
            } else {
                WhsStorageInventory whsStorageInventory = new WhsStorageInventory();
                whsStorageInventory.setUuid(uuid);
                whsStorageInventory.setBoxNote(boxNote);
                whsStorageInventory.setQuantity(1.0);
                whsStorageInventory.setAvailableQty(1.0);
                /** 物料在对应储位不存在数据，则新建一条 储位-物料-数量 的数据； */
                whsStorageInventoryMapper.insert(whsStorageInventory);
            }

            return ResponseResult.success();
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("Error when update storage Inventory X");
        }
    }

    // 更新储位库存 贸易货上架
    @Override
    public ResponseResult updateStorageInventoryM(String uuid, String materialNo, Double qty, String deliveryNoteSap,
            String userId) {
        if (null == qty || qty <= 0) {
            return ResponseResult.error("Qty is less then 0");
        }

        try {
            /** 如果该物料在该储位已经存在，则更新对应储位下物料的库存数量；如果不存在，则新建一条 储位-物料-数量 的数据； */
            QueryWrapper<WhsStorageInventory> wrapper = new QueryWrapper<WhsStorageInventory>().eq("UUID", uuid)
                    .eq("MATERIAL_NO", materialNo);
            WhsStorageInventory storageInventory = whsStorageInventoryMapper.selectOne(wrapper);
            WhsStorageInventory whsStorageInventory = new WhsStorageInventory();
            if (storageInventory != null) {
                whsStorageInventory.setQuantity(storageInventory.getQuantity() + qty);
                whsStorageInventory.setAvailableQty(storageInventory.getAvailableQty() + qty);
                /** 物料在对应储位已存在数据，则更新库存数量和可用数量； */
                whsStorageInventoryMapper.update(whsStorageInventory, wrapper);
            } else {
                whsStorageInventory.setUuid(uuid);
                whsStorageInventory.setMaterialNo(materialNo);
                whsStorageInventory.setQuantity(qty);
                whsStorageInventory.setAvailableQty(qty);
                /** 物料在对应储位不存在数据，则新建一条 储位-物料-数量 的数据； */
                whsStorageInventoryMapper.insert(whsStorageInventory);
            }
            WhsStorage whsStorage = iWhsStorageService.getWhsStorageByUuid(uuid);
            /** 记录自管仓 贸易货 按物料 上架 增加储位库存日志 */
            iWhsOperateLogService.insertWhsOperateLogMS(uuid, materialNo, qty, deliveryNoteSap,
                    TRADE_GOODS_INTO_STORAGE, userId, whsStorage.getWerks(), whsStorage.getWhsLocationCode(), "");
            return ResponseResult.success();
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("Error when update storage inventory M");
        }

    }

    /**
     * 根据箱码，储位编号删除储位库存
     */
    @Override
    public int deleteStorageByBoxNoteStorageId(String uuid, String boxNote) {
        try {
            return whsStorageInventoryMapper
                    .delete(new QueryWrapper<WhsStorageInventory>().eq("UUID", uuid).eq("BOX_NOTE", boxNote));
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }

    // 更新储位库存 备件货下架
    @Override
    public ResponseResult updateDeductTaskDtlX(String uuid, String boxNote, String deliveryNoteSap, String userId) {
        try {
            whsStorageInventoryMapper
                    .delete(new QueryWrapper<WhsStorageInventory>().eq("UUID", uuid).eq("BOX_NOTE", boxNote));
            WhsStorage whsStorage = iWhsStorageService.getWhsStorageByUuid(uuid);
            iWhsOperateLogService.insertWhsOperateLogBX(uuid, boxNote, 1.0, deliveryNoteSap, SPARE_PARTS_OUT_STORAGE,
                    userId, whsStorage.getWerks(), whsStorage.getWhsLocationCode());
            return ResponseResult.success();
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("Error when deduct box inventory from storage");
        }
    }

    // 更新储位库存 贸易货下架
    @Override
    public ResponseResult updateDeductTaskDtlM(String uuid, String materialNo, Double qty, String deliveryNoteSap,
            String userId) {
        if (null == qty || qty <= 0) {
            return ResponseResult.error("The  deduct qty is less then 0");
        }

        try {
            /** 如果该物料在该储位已经存在，则更新对应储位下物料的库存数量；如果不存在，直接返回； */
            QueryWrapper<WhsStorageInventory> wrapper = new QueryWrapper<WhsStorageInventory>().eq("UUID", uuid)
                    .eq("MATERIAL_NO", materialNo);
            WhsStorageInventory storageInventory = whsStorageInventoryMapper.selectOne(wrapper);
            WhsStorageInventory whsStorageInventory = new WhsStorageInventory();
            if (storageInventory != null) {
                Double storageQty = storageInventory.getQuantity();
                if (storageQty < qty) {
                    // 如果当前储位的库存小于要下架的库存，返回错误
                    return ResponseResult.error("Inventory QTY less then the QTY your want to deduct");
                }
                whsStorageInventory.setQuantity(storageQty - qty);
                whsStorageInventory.setAvailableQty(storageInventory.getAvailableQty() - qty);
                if (whsStorageInventory.getQuantity() <= 0) {
                    // 库存数量为0，删除
                    whsStorageInventoryMapper.delete(wrapper);
                } else {
                    /** 物料在对应储位已存在数据，则更新库存数量和可用数量； */
                    whsStorageInventoryMapper.update(whsStorageInventory, wrapper);
                }
                WhsStorage whsStorage = iWhsStorageService.getWhsStorageByUuid(uuid);
                /** 记录自管仓 贸易货 按物料 上架 增加储位库存日志 */
                iWhsOperateLogService.insertWhsOperateLogMS(uuid, materialNo, qty, deliveryNoteSap, GOODS_OUT_STORAGE,
                        userId, whsStorage.getWerks(), whsStorage.getWhsLocationCode(), "");
                return ResponseResult.success();
            } else {
                return ResponseResult.error("The material not exist in the given storage");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("Error When deduct storage inventory");
        }
    }

    // 查箱码所在储位
    @Override
    public WhsStorageInventory getBoxNoteStorage(String boxNote) {
        return whsStorageInventoryMapper.selectOne(new QueryWrapper<WhsStorageInventory>().eq("BOX_NOTE", boxNote));
    }

    // 查找Material在储位的库存
    @Override
    public WhsStorageInventory getMaterialOnStorage(String materialNo, String storageNoUUID) {
        return whsStorageInventoryMapper.selectOne(
                new QueryWrapper<WhsStorageInventory>().eq("UUID", storageNoUUID).eq("MATERIAL_NO", materialNo));
    }

    @Override
    public String getAvailableQtyByUuidBoxNote(String storageUuid, String boxNote) {
        return this.baseMapper.getAvailableQtyByUuidBoxNote(storageUuid, boxNote);
    }

    @Override
    public WhsStorageInventory getStorageBoxNote(String storageUuid, String boxNote) {
        return this.baseMapper
                .selectOne(new QueryWrapper<WhsStorageInventory>().eq("UUID", storageUuid).eq("BOX_NOTE", boxNote));
    }

    @Override
    public int deleteStorageBoxNote(String boxNote) {
        /** 箱码具有唯一性，扣减储位库存不传 储位uuid 直接按箱码删除储位库存 */
        return this.baseMapper.delete(new QueryWrapper<WhsStorageInventory>().eq("BOX_NOTE", boxNote));

    }

    /**
     * 贸易货根据储位 uuid 和 物料编号查询库存数量
     */
    @Override
    public WhsStorageInventory getStorageMaterialNo(String storageUuid, String materialNo) {
        return this.baseMapper.selectOne(new QueryWrapper<WhsStorageInventory>().eq("UUID", storageUuid)
                .eq("MATERIAL_NO", materialNo).ge("AVAILABLE_QTY", 0));
    }

    /**
     * 贸易货根据储位uuid，物料号，数量扣减更新储位库存
     */
    @Override
    public synchronized int updateWhsStorage(String storageUuid, String materialNo, double qty) {
        if (qty == 0) {
            return -1;
        }
        // WhsStorageInventory whsStorageInventory = this.baseMapper.selectOne(new
        // QueryWrapper<WhsStorageInventory>().eq("UUID", storageUuid).eq("MATERIAL_NO",
        // materialNo).gt("AVAILABLE_QTY", 0));
        Map<String, Object> whsStorageInventoryMap = this.baseMapper.getWhsStorageInventoryByUuidMaterialNo(storageUuid,
                materialNo);
        if (whsStorageInventoryMap == null) {
            return -1;
        }
        double quantity = Double.parseDouble(whsStorageInventoryMap.get("quantity").toString()) - qty;
        double availableQty = Double.parseDouble(whsStorageInventoryMap.get("availableQty").toString()) - qty;
        if (quantity < 0 || availableQty < 0) {
            return -1;
        }
//        if (quantity == 0 && availableQty == 0) {
//            this.baseMapper.delete(
//                    new QueryWrapper<WhsStorageInventory>().eq("UUID", storageUuid).eq("MATERIAL_NO", materialNo));
//            return 1;
//        }
        WhsStorageInventory whsStorageInventory = new WhsStorageInventory();
        whsStorageInventory.setQuantity(quantity);
        whsStorageInventory.setAvailableQty(availableQty);
        this.baseMapper.update(whsStorageInventory,
                new QueryWrapper<WhsStorageInventory>().eq("UUID", storageUuid).eq("MATERIAL_NO", materialNo));
        return 1;
    }


    @Override
    public synchronized int updateWhsStorageNotUpdate(String storageUuid, String materialNo, double qty) {
        if (qty == 0) {
            return -1;
        }
        Map<String, Object> whsStorageInventoryMap = this.baseMapper.getWhsStorageInventoryByUuidMaterialNo(storageUuid,
                materialNo);
        if (whsStorageInventoryMap == null) {
            return -1;
        }
        double quantity = Double.parseDouble(whsStorageInventoryMap.get("quantity").toString()) - qty;
        double availableQty = Double.parseDouble(whsStorageInventoryMap.get("availableQty").toString()) - qty;
        if (quantity < 0 || availableQty < 0) {
            return -1;
        }
        return 1;
    }

    /**
     * 根据箱码，储位编号更新储位库存
     */
    @Override
    public ResponseResult updateWhsStorageX(JSONObject updateDoc, String userId) {
        try {

            String originalStorageUuid = updateDoc.getString("originalStorageUuid");
            String targetStorageUuid = updateDoc.getString("targetStorageUuid");
            String boxNote = updateDoc.getString("boxNote");
            String documentNumber = updateDoc.getString("documentNumber");
            String remarks = updateDoc.getString("remarks");
            String werks = updateDoc.getString("werks");
            String whsLocationCode = updateDoc.getString("whsLocationCode");

            if (StringUtils.isEmpty(targetStorageUuid) || StringUtils.isEmpty(boxNote)) {
                return ResponseResult.error("targetStorageUuid and boxNote are mandatory required");
            }
            if (StringUtils.isEmpty(remarks)) {
                remarks = "Move boxNote: " + boxNote + " from storage: " + originalStorageUuid + " to stoage: "
                        + targetStorageUuid;
            }
            /* boxNote应该是唯一的，所以理论上来说应该可以只按照boxNote来查找 */
            QueryWrapper<WhsStorageInventory> queryWrapper = new QueryWrapper<WhsStorageInventory>().eq("BOX_NOTE",
                    boxNote);

            WhsStorageInventory whsStorageInventory = this.baseMapper.selectOne(queryWrapper);
            if (null == whsStorageInventory) {
                // boxNote在储位库存里不存在，验证是否在仓库存库存里存在，如果在仓库库存存在，就下接insert到储位库存
                int inWhsInventoryInfo = whsInventoryInfoMapper.validateBoxNote(boxNote, werks, whsLocationCode);
                if (inWhsInventoryInfo > 0) {
                    whsStorageInventory = new WhsStorageInventory();
                    whsStorageInventory.setUuid(targetStorageUuid);
                    whsStorageInventory.setQuantity(1.0);
                    whsStorageInventory.setAvailableQty(1.0);
                    whsStorageInventory.setBoxNote(boxNote);
                    int insertRes = this.baseMapper.insert(whsStorageInventory);
                    if (insertRes > 0) {
                        iWhsOperateLogService.insertWhsOperateLogBI(targetStorageUuid, boxNote, 1.0, documentNumber,
                                SPARE_PARTS_INTO_STORAGE, userId, remarks, werks, whsLocationCode);
                        return ResponseResult.success();
                    } else {
                        return ResponseResult.error("Error when insert storage inventory ");
                    }
                } else {
                    return ResponseResult
                            .error("The given boxNote: " + boxNote + " not exist in warehouse storage for werks: "
                                    + werks + " whsLocationCode: " + whsLocationCode);
                }
            }
            whsStorageInventory.setUuid(targetStorageUuid);
            int res = this.baseMapper.update(whsStorageInventory, queryWrapper);
            if (res <= 0) {
                return ResponseResult.error("Error when update storage inventory");
            }
            iWhsOperateLogService.insertWhsOperateLogBX(originalStorageUuid, boxNote, 1.0, documentNumber,
                    SPARE_PARTS_OUT_STORAGE, userId, remarks, werks, whsLocationCode);
            iWhsOperateLogService.insertWhsOperateLogBI(targetStorageUuid, boxNote, 1.0, documentNumber,
                    SPARE_PARTS_INTO_STORAGE, userId, remarks, werks, whsLocationCode);

            return ResponseResult.success();
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("Failed whild update Wharehouse storage");
        }
    }

    @Override
    public List<WhsStorageInventory> getStorageListByBoxNoteList(List<String> boxNoteList) {
        return this.baseMapper.selectList(new QueryWrapper<WhsStorageInventory>().in("UUID", boxNoteList));
    }

    // 备件货上架
    @Override
    public ResponseResult updateStorageInventoryX(String uuid, String operateTime, String boxNote) {
        WhsStorageInventory whsStorageInventory = new WhsStorageInventory();
        whsStorageInventory.setUuid(uuid);
        whsStorageInventory.setOperateTime(operateTime);
        whsStorageInventory.setBoxNote(boxNote);
        whsStorageInventory.setQuantity(1.0);
        System.out.println("准备存储的的箱信息是" + whsStorageInventory.toString());
        try {
            whsStorageInventoryMapper.update(whsStorageInventory,
                    new QueryWrapper<WhsStorageInventory>().eq("BOX_NOTE", boxNote));
            return ResponseResult.success().add("message", "插入成功");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
            return ResponseResult.error("插入失败" + e.getMessage());
        }
    }

    @Override
    public void insertStorageInventory(String uuid, String operateTime, String boxNote) {
        WhsStorageInventory whsStorageInventory = new WhsStorageInventory();
        whsStorageInventory.setBoxNote(boxNote);
        whsStorageInventory.setUuid(uuid);
        if (StringUtils.isNotEmpty(operateTime)) {
            whsStorageInventory.setOperateTime(operateTime);
        }
        whsStorageInventory.setQuantity(1.0);
        whsStorageInventory.setAvailableQty(1.0);
        whsStorageInventoryMapper.insert(whsStorageInventory);
        // iWhsOperateLogService.insertWhsOperateLogBS(uuid, boxNote, 1.0, null,
        // SPARE_PARTS_INTO_STORAGE, userId);
    }

    @Override
    public Optional<WhsStorageInventory> getStorageInventoryByBoxNo(String boxNote) {
        Optional<WhsStorageInventory> wsi = Optional.ofNullable(whsStorageInventoryMapper
                .selectOne(new QueryWrapper<WhsStorageInventory>().eq("BOX_NOTE", boxNote).eq("QUANTITY", 1.0)));
        return wsi;
    }

    /**
     * 盘盈盘亏储位库存操作调用方法: discrepancy 为操作数的绝对值；inventoryActionType 701盘盈，702盘亏；
     * 如果贸易货盘亏时，该物料在储位不存在则报错；如果盘亏数量大于系统账数量则报错；
     *
     * @param inventoryCheckAction
     * @param materialNo
     * @param boxNote
     * @param discrepancy
     * @param storageUuid
     * @return
     */
    @Override
    public synchronized int updateWhsStorageInventory(InventoryCheckAction inventoryCheckAction, String materialNo,
            String boxNote, double discrepancy, String storageUuid, String userId, String taskRowId) {
        try {
            String icaUuid = inventoryCheckAction.getUuid();
            String werks = inventoryCheckAction.getWerks();
            String whsLocationCode = inventoryCheckAction.getWhsLocationCode();
            String goodsType = inventoryCheckAction.getInventoryCheckType();
            String moveType = inventoryCheckAction.getInventoryActionType();
            if ("X".equals(goodsType)) {
                if ("701".equals(moveType)) {
                    ResponseResult updateInventoryResult = iWhsInventoryInfoService.updateWhsInventoryX(werks,
                            whsLocationCode, boxNote, 1, "add", userId);
                    if (updateInventoryResult.getCode() != 200) {
                        return -1;
                    }
                    iWhsOperateLogService.insertWhsOperateLog("1", storageUuid, "", boxNote, discrepancy, "9", icaUuid,
                            SPARE_PARTS_INTO_WHS, userId, "自管仓备件盘盈入仓库", werks, whsLocationCode, taskRowId);

                    ResponseResult updateStorageInventory = updateStorageInvX(storageUuid, boxNote, 1, "add");
                    if (updateStorageInventory.getCode() != 200) {
                        return -1;
                    }
                    iWhsOperateLogService.insertWhsOperateLog("2", storageUuid, "", boxNote, discrepancy, "7", icaUuid,
                            SPARE_PARTS_INTO_STORAGE, userId, "自管仓备件盘盈入储位", werks, whsLocationCode, taskRowId);
                    return 1;
                }
                if ("702".equals(moveType)) {
                    ResponseResult updateInventoryResult = iWhsInventoryInfoService.updateWhsInventoryX(werks,
                            whsLocationCode, boxNote, 1, "sub", userId);
                    if (updateInventoryResult.getCode() != 200) {
                        return -1;
                    }
                    iWhsOperateLogService.insertWhsOperateLog("1", storageUuid, "", boxNote, discrepancy, "10", icaUuid,
                            SPARE_PARTS_OUT_WHS, userId, "自管仓备件盘亏出仓库", werks, whsLocationCode, taskRowId);

                    ResponseResult updateStorageInventory = updateStorageInvX(storageUuid, boxNote, 1, "sub");
                    if (updateStorageInventory.getCode() != 200) {
                        return -1;
                    }
                    iWhsOperateLogService.insertWhsOperateLog("2", storageUuid, "", boxNote, discrepancy, "8", icaUuid,
                            SPARE_PARTS_OUT_STORAGE, userId, "自管仓备件盘亏出储位", werks, whsLocationCode, taskRowId);
                    return 1;
                }
                return -1;
            }
            if ("M".equals(goodsType)) {
                if ("701".equals(moveType)) {
                    ResponseResult addStorageInventoryM = updateStorageInventoryM(storageUuid, materialNo, discrepancy,
                            "add");
                    if (addStorageInventoryM.getCode() != 200) {
                        return -1;
                    }
                    iWhsOperateLogService.insertWhsOperateLog("2", storageUuid, materialNo, "", discrepancy, "7",
                            icaUuid, TRADE_GOODS_INTO_STORAGE, userId, "自管仓贸易货盘盈入储位", werks, whsLocationCode, taskRowId);
                    return 1;
                }
                if ("702".equals(moveType)) {
                    ResponseResult subStorageInventoryM = updateStorageInventoryM(storageUuid, materialNo, discrepancy,
                            "sub");
                    if (subStorageInventoryM.getCode() != 200) {
                        return -1;
                    }
                    iWhsOperateLogService.insertWhsOperateLog("2", storageUuid, materialNo, "", discrepancy, "8",
                            icaUuid, GOODS_OUT_STORAGE, userId, "自管仓贸易货盘亏出储位", werks, whsLocationCode, taskRowId);
                    return 1;
                }
                return -1;
            }
            return -1;
        } catch (Exception e) {
            e.printStackTrace();
            return -2;
        }
    }

    /**
     * 贸易货根据储位uuid，物料号，数量增加更新储位库存。不存在则新增数据，存在则更新数据。返回结果 > 0 表示成功。
     */
    @Override
    public synchronized int updateWhsStorageInventoryMOld(String storageUuid, String materialNo, double qty) {
        synchronized (this) {
            try {
                if (qty == 0) {
                    return -1;
                }
                WhsStorageInventory whSI = this.baseMapper.selectOne(
                        new QueryWrapper<WhsStorageInventory>().eq("UUID", storageUuid).eq("MATERIAL_NO", materialNo));
                if (whSI == null) {
                    WhsStorageInventory whsStorageInventory = new WhsStorageInventory();
                    whsStorageInventory.setUuid(storageUuid);
                    whsStorageInventory.setMaterialNo(materialNo);
                    whsStorageInventory.setQuantity(qty);
                    whsStorageInventory.setAvailableQty(qty);
                    return this.baseMapper.insert(whsStorageInventory);
                }
                double quantity = whSI.getQuantity() + qty;
                double availableQty = whSI.getAvailableQty() + qty;

                WhsStorageInventory storageInventory = new WhsStorageInventory();
                storageInventory.setQuantity(quantity);
                storageInventory.setAvailableQty(availableQty);
                return this.baseMapper.update(storageInventory,
                        new QueryWrapper<WhsStorageInventory>().eq("UUID", storageUuid).eq("MATERIAL_NO", materialNo));
            } catch (Exception e) {
                e.printStackTrace();
                return -2;
            }
        }
    }

    /**
     * 检查是否有足够库存
     */
    @Override
    public ResponseResult checkStorageInventory(JSONArray storageList, String materialNo) {
        for (int i = 0; i < storageList.size(); i++) {
            JSONObject storageObj = storageList.getJSONObject(i);
            String storageUuid = storageObj.getString("storageUuid");
            double qty = storageObj.getDouble("qty");
            WhsStorageInventory whSI = this.baseMapper.selectOne(
                    new QueryWrapper<WhsStorageInventory>().eq("UUID", storageUuid).eq("MATERIAL_NO", materialNo));
            if (null == whSI || whSI.getQuantity() < qty) {
                return ResponseResult.error(materialNo + " on storage " + storageObj.getString("storageNo")
                        + " do not have enough inventory, storageUuid ："+storageUuid+", WhsStorageInventory ："+whSI);
            }
        }
        return ResponseResult.success();
    }

    /**
     * 线程安全控制————贸易货储位库存操作，operateType = add 加库存；operateType = sub 减库存； 加减库存时 qty
     * 都取正数；此法不带操作日志；
     */
    @Override
    public synchronized ResponseResult updateStorageInventoryM(String storageUuid, String materialNo, double qty,
            String operateType) {
        if (StringUtils.isEmpty(storageUuid) || StringUtils.isEmpty(materialNo)) {
            return ResponseResult.error().add("error", "storageUuid 或 materialNo 不能为空");
        }
        if (qty == 0) {
            return ResponseResult.error().add("error", "qty 不能为0");
        }
        try {
            QueryWrapper<WhsStorageInventory> queryWrapper = new QueryWrapper<WhsStorageInventory>()
                    .eq("UUID", storageUuid).eq("MATERIAL_NO", materialNo);
            WhsStorageInventory storageInventory = this.baseMapper.selectOne(queryWrapper);
            if ("add".equals(operateType)) {
                // 加储位库存——已存在更新；不存在则新增；
                if (null != storageInventory) {
                    double quantity = storageInventory.getQuantity() + qty;
                    double availableQty = storageInventory.getAvailableQty() + qty;
                    WhsStorageInventory inventory = new WhsStorageInventory();
                    inventory.setQuantity(quantity);
                    inventory.setAvailableQty(availableQty);
                    this.baseMapper.update(inventory, queryWrapper);
                    return ResponseResult.success();
                } else {
                    WhsStorageInventory whsStorageInventory = new WhsStorageInventory();
                    whsStorageInventory.setUuid(storageUuid);
                    whsStorageInventory.setMaterialNo(materialNo);
                    whsStorageInventory.setQuantity(qty);
                    whsStorageInventory.setAvailableQty(qty);
                    this.baseMapper.insert(whsStorageInventory);
                    return ResponseResult.success();
                }
            }
            if ("sub".equals(operateType)) {
                // 减储位库存，操作数大于库存则返回错误提示；操作数等于库存则删除该库存；操作数小于库存则更新该库存；
                if (null != storageInventory) {
                    if (qty > storageInventory.getAvailableQty()) {
                        return ResponseResult.error().add("error", materialNo + "在储位" + storageUuid + "库存不足，请检查重试");
                    }
                    if (qty == storageInventory.getAvailableQty()) {
                        this.baseMapper.delete(queryWrapper);
                        return ResponseResult.success();
                    }
                    if (qty < storageInventory.getAvailableQty()) {
                        storageInventory.setQuantity(storageInventory.getQuantity() - qty);
                        storageInventory.setAvailableQty(storageInventory.getAvailableQty() - qty);
                        this.baseMapper.update(storageInventory, queryWrapper);
                        return ResponseResult.success();
                    }
                } else {
                    return ResponseResult.error().add("error", materialNo + "在储位" + storageUuid + "不存在，请检查重试");
                }
            }
            return ResponseResult.error().add("error", "操作类型不正确");
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error().add("error", e.getMessage() + "\nfunction name: updateStorageInventoryM");
        }
    }

    /**
     * 线程安全控制————备件货储位库存操作，operateType = add 加库存；operateType = sub 减库存； 加减库存时 qty
     * 都取1；此法不带操作日志；
     */
    @Override
    public synchronized ResponseResult updateStorageInvX(String storageUuid, String boxNote, double qty,
            String operateType) {
        try {
            if (StringUtils.isEmpty(storageUuid) || StringUtils.isEmpty(boxNote)) {
                return ResponseResult.error().add("error", "storageUuid 或 boxNote 不能为空");
            }
            if (qty == 0) {
                return ResponseResult.error().add("error", "qty 不能为0");
            }
            QueryWrapper<WhsStorageInventory> queryWrapper = new QueryWrapper<WhsStorageInventory>()
                    .eq("UUID", storageUuid).eq("BOX_NOTE", boxNote);
            WhsStorageInventory storageInventory = this.baseMapper.selectOne(queryWrapper);
            // 箱码具有唯一性 加储位库存——已存在则报错；不存在则新增；
            if ("add".equals(operateType)) {
                if (null != storageInventory) {
                    return ResponseResult.error().add("error", "箱码" + boxNote + "在储位" + storageUuid + "已存在，请勿重复操作");
                } else {
                    WhsStorageInventory whsStorageInventory = new WhsStorageInventory();
                    whsStorageInventory.setUuid(storageUuid);
                    whsStorageInventory.setBoxNote(boxNote);
                    whsStorageInventory.setQuantity(qty);
                    whsStorageInventory.setAvailableQty(qty);
                    this.baseMapper.insert(whsStorageInventory);
                    return ResponseResult.success();
                }
            }
            // 箱码具有唯一性 减储位库存——已存在则删除；不存在则报错；
            if ("sub".equals(operateType)) {
                if (null != storageInventory) {
                    this.baseMapper.delete(queryWrapper);
                    return ResponseResult.success();
                } else {
                    return ResponseResult.error().add("error", "箱码" + boxNote + "在储位" + storageUuid + "不存在，请检查重试");
                }
            }
            return ResponseResult.error().add("error", "操作类型不正确");
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error().add("error", e.getMessage() + "\nfunction name: updateStorageInventoryX");
        }
    }

    @Override
    public Map<String, Object> getPageMap(List<String> werks, List<String> whsLocationCode, List<String> storageArea,
            List<String> shelfNo, List<String> shelfLayer, List<String> shelfCell, List<String> storageNo,
            List<String> materialNo, String storageCategory, List<String> boxNote, int pageNo, int pageSize) {
        Page<Map<String, Object>> pages = new Page<>(pageNo, pageSize);
        List<Map<String, Object>> pageMaData = this.baseMapper.pageDataMap(pages, werks, whsLocationCode, storageArea,
                shelfNo, shelfLayer, shelfCell, storageNo, materialNo, boxNote);

        JSONArray arr = JSONArray.parseArray(JSON.toJSONString(pageMaData));
        for (int i = 0; i < arr.size(); i++) {
            JSONObject json = arr.getJSONObject(i);
            if (!StringUtils.isEmpty(json.getString("boxNote"))) {
                List<Map<String, Object>> list = iSapBoxNoteService.getNewBox(json.getString("boxNote"));
                if (list.size() > 0) {
                    json.put("hasChlidren", 1);
                    json.put("kid", iSapBoxNoteService.getNewBox(json.getString("boxNote")));
                } else {
                    json.put("hasChildren", 0);
                }
            }
            // json.put("children",iSapBoxNoteService.checkNewBox(json.getString("boxNote")));
        }
        System.out.println(arr);
        // pages.setRecords(pageMaData);
        HashMap<String, Object> map = new HashMap<>();
        map.put("page", pages);
        map.put("arr", arr);
        return map;

    }

    @Override
    public ResponseResult getWSInventory(String werks, String whsLocationCode, List<String> materialNo,
            List<String> boxNote) {
        if (StringUtils.isEmpty(werks) || StringUtils.isEmpty(whsLocationCode)
                || (null == materialNo && null == boxNote) || (materialNo.size() <= 0 && boxNote.size() <= 0)) {
            return ResponseResult.error("Werks, Whslocationcode , materialNo or Boxnote are mandatory required");
        }

        return ResponseResult.success().add("storageInvList",
                this.baseMapper.getWSInventory(werks, whsLocationCode, materialNo, boxNote));
    }

	@Override
	public ResponseResult getWhsStockList(WhsSearchDTO dto) {
		Integer pageNo = dto.getPageNo();
		Integer pageSize = dto.getPageSize();
		String storageCategory = dto.getGoodsType();
		Page<Map<String, Object>> pages = new Page<>(pageNo, pageSize);
        List<Map<String, Object>> pageData = new ArrayList<>();
        if ("M".equals(storageCategory)) {
            pageData = whsStorageInventoryMapper.getWhsStockMPage(pages, dto);
        } else if ("X".equals(storageCategory)) {
            pageData = whsStorageInventoryMapper.getWhsStockXPage(pages, dto);
        } else {
            pageData = whsStorageInventoryMapper.getAllWhsStockPage(pages, dto);
        }
        String nowDate = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        // 计算库存件数
        if (CollectionUtils.isNotEmpty(pageData)) {
        	for (Map<String, Object> map : pageData) {
        		BigDecimal availableQty = BigDecimal.ZERO;
        		if(map.get("availableQty")!=null){
                    if (StringUtils.isNotEmpty(map.get("availableQty").toString())) {
                        availableQty = new BigDecimal(map.get("availableQty").toString());
                    }
                }

        		BigDecimal divide = availableQty.multiply(new BigDecimal(map.get("denominator").toString())).divide(new BigDecimal(map.get("numerator").toString()), 2, BigDecimal.ROUND_HALF_UP);
        		map.put("nowDate", nowDate);
        		map.put("pieceQty", divide);
        	}
        }
        pages.setRecords(pageData);
        return ResponseResult.success().add("storageInventory", pages);
	}

	@Override
	public ResponseResult getWSInventoryByBoxNote(List<String> boxNote) {
        return ResponseResult.success().add("storageInvList", this.baseMapper.getWSInventoryByBox(boxNote));
	}

    // @Override
    // public Map<String,Object> getPageMap(List<String> werks, List<String>
    // whsLocationCode, List<String> storageArea, List<String> shelfNo, List<String>
    // shelfLayer, List<String> shelfCell, List<String> storageNo, List<String>
    // materialNo, String storageCategory, List<String> boxNote, int pageNo, int
    // pageSize){
    //// int pageNo = !doc.containsKey("pageNo") || doc.get("pageNo") == null ||
    // "".equals(doc.get("pageNo")) ? 1 :
    // Integer.parseInt(doc.get("pageNo").toString());
    //// int pageSize = !doc.containsKey("pageSize") || doc.get("pageSize") == null
    // || "".equals(doc.get("pageSize")) ? 20 :
    // Integer.parseInt(doc.get("pageSize").toString());
    ////
    ////
    //// String boxNote = !doc.containsKey("boxNote") || doc.get("boxNote") == null
    // || "".equals(doc.get("boxNote")) ? null : doc.getString("boxNote");
    //// List<String> werks = !doc.containsKey("boxNote") || doc.get("boxNote") ==
    // null || "".equals(doc.get("boxNote")) ? null : doc.getString("boxNote");
    // Page<Map<String, Object>> pages = new Page<>(pageNo, pageSize);
    //// List<Map<String, Object>> pageMaData = this.baseMapper.pageDataMap(werks,
    // whsLocationCode, storageArea, shelfNo, shelfLayer, shelfCell, storageNo,
    // boxNote);
    //
    //// JSONArray arr = JSONArray.parseArray(JSON.toJSONString(pageMaData));
    // for(int i=0;i<arr.size();i++){
    // JSONObject json = arr.getJSONObject(i);
    // System.out.println(json.getString("boxNote"));
    //// json.put("children",iSapBoxNoteService.checkNewBox(json.getString("boxNote")));
    // List<Map<String,Object>> list
    // =iSapBoxNoteService.getNewBox(json.getString("boxNote"));
    // if(list.size()>0){
    // json.put("hasChlidren",1);
    // json.put("children",iSapBoxNoteService.getNewBox(json.getString("boxNote")));
    // }else{
    // json.put("hasChildren",0);
    // }
    // }
    // System.out.println(arr);
    // pages.setRecords(pageMaData);
    // HashMap<String, Object> map = new HashMap<>();
    // map.put("page",pages);
    // map.put("arr",arr);
    // return map;
    //// return pages;
    // }

}
