# LotInventoryManagerImpl.java

    package com.mycim.server.asm.manager.impl;

    import com.fa.sesa.exception.Assert;
    import com.fa.sesa.exception.Errors;
    import com.mycim.framework.jdbc.Page;
    import com.mycim.framework.utils.lang.StringUtils;
    import com.mycim.framework.utils.lang.collections.MapUtils;
    import com.mycim.server.asm.dao.LotInventoryDAO;
    import com.mycim.server.asm.dao.MaterialDAO;
    import com.mycim.server.asm.dao.WarehouseDAO;
    import com.mycim.server.asm.manager.LotInventoryManager;
    import com.mycim.valueobject.MessageIdList;
    import com.mycim.valueobject.bas.TransactionLog;
    import com.mycim.valueobject.consts.TransactionNames;
    import com.mycim.valueobject.inv.InventoryTransHistoryDO;
    import com.mycim.valueobject.inv.LotInventoryDO;
    import com.mycim.valueobject.inv.value.WarehouseNames;
    import com.mycim.valueobject.wip.LotConsumesMaterialHistory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.util.*;

    /**
     * @author shijie.deng
     * @date 2019/8/30
     **/
    @Service
    @Transactional
    public class LotInventoryManagerImpl implements LotInventoryManager {

        @Autowired
        private LotInventoryDAO lotInventoryDAO;

        @Autowired
        private WarehouseDAO warehouseDAO;

        @Autowired
        private MaterialDAO materialDAO;

        @Override
        public void saveLotInventory(LotInventoryDO lotInventory) {
            Boolean isExisted = lotInventoryDAO
                    .checkLotInventoryIsExistedInWarehouse(lotInventory.getLotNumber(), lotInventory.getItemRrn(),
                                                           lotInventory.getWarehouseRrn());
            if (isExisted) {
                lotInventoryDAO.updateLotInventory(lotInventory);
                lotInventoryDAO.updateLotInventoryExt(lotInventory);
                lotInventoryDAO.updateLotInventoryForQty(lotInventory);
            } else {
                lotInventoryDAO.insertLotInventory(lotInventory);
                lotInventoryDAO.insertLotInventoryExt(lotInventory);
            }
        }

        @Override
        public void deleteLotInventory(String lotNumber, Long itemRrn, Long warehouseRrn) {
            lotInventoryDAO.deleteLotInventory(lotNumber, itemRrn, warehouseRrn);
            lotInventoryDAO.deleteLotInventoryExt(lotNumber, itemRrn, warehouseRrn);
        }

        @Override
        public void updateLotInventory(LotInventoryDO lotInventoryDO) {
            lotInventoryDAO.updateLotInventory(lotInventoryDO);
            lotInventoryDAO.updateLotInventoryExt(lotInventoryDO);
        }

        @Override
        public void updateLotInventoryForQty(LotInventoryDO lotInventory) {
            lotInventoryDAO.updateLotInventoryForQty(lotInventory);
        }

        @Override
        public LotInventoryDO getLotInventory(String lotNumber, Long itemRrn, Long warehouseRrn) {
            return lotInventoryDAO.getLotInventoryAndExt(lotNumber, itemRrn, warehouseRrn);
        }

        @Override
        public List<LotInventoryDO> getLotInventoryList(Long itemRrn, Long warehouseRrn, String lotNumber,
                                                        String transType) {
            return lotInventoryDAO.getLotInventoryList(itemRrn, warehouseRrn, lotNumber, transType);
        }

        @Override
        public String getLotInventoryStatus(String lotNumber, double totalQty, double transQty) {
            Assert.isFalse(transQty <= 0, Errors.create().key(MessageIdList.ASM_INVALID_OP_QTY).content("{} 操作数量不能小于等于0!").args(lotNumber).build());
            Assert.isFalse(transQty > totalQty, Errors.create().key(MessageIdList.ASM_QTY_INSUFFICIENT).content("{} 库存数量不足!").args(lotNumber).build());
            if (Double.doubleToLongBits(transQty) == Double.doubleToLongBits(totalQty)) {
                return WarehouseNames.CLOSE_STATUS;
            } else {
                return WarehouseNames.ACTIVE_STATUS;
            }
        }

        @Override
        public Page pageLotInventoryList(Page page, Long itemRrn, Long warehouseRrn, String lotNumber) {
            return lotInventoryDAO.pageLotInventoryList(page, itemRrn, warehouseRrn, lotNumber);
        }

        @Override
        public void consumeMaterialFromWarehouseForLot(Map<String, Object> issueData) {

            TransactionLog transactionLog = (TransactionLog) issueData.get("transactionLog");

            long transSequence = issueData.get("transSequence") != null ? MapUtils.getLong(issueData, "transSequence") : 0;

            String lotId = MapUtils.getString(issueData, "lotId");
            long lotRrn = MapUtils.getLongValue(issueData, "lotRrn");
            long lotStepSequence = MapUtils.getLongValue(issueData, "stepSequence");
            long facilityRrn = MapUtils.getLongValue(issueData, "facilityRrn");
            String returnflag = MapUtils.getString(issueData, "returnflag");
            long sequence = transSequence + 1;

            Collection rawMaterials = (Collection) issueData.get("rawMaterials");
            for (Iterator iterator = rawMaterials.iterator(); iterator.hasNext(); ) {
                Map rawMaterial = (HashMap) iterator.next();

                String lotNumber = MapUtils.getString(rawMaterial, "lotNumber");
                long itemRrn = MapUtils.getLongValue(rawMaterial, "itemRrn");
                long warehouseRrn = MapUtils.getLongValue(rawMaterial, "wareHouseRrn");
                double issueQty = MapUtils.getDoubleValue(rawMaterial, "specifiedQty");
                String lotBox = MapUtils.getString(rawMaterial, "lotBox");

                LotInventoryDO lotInventory = lotInventoryDAO.getLotInventoryAndExt(lotNumber, itemRrn, warehouseRrn);

                lotInventory.setAdjustQty(0D);
                lotInventory.setIssueQty(issueQty);
                lotInventory.setReceiptQty(0D);

                InventoryTransHistoryDO inventoryTransHistory = new InventoryTransHistoryDO();

                inventoryTransHistory.setTransRrn(transactionLog.getTransRrn());
                inventoryTransHistory.setTransSequence(sequence++);
                if (StringUtils.isNotBlank(returnflag)) {
                    inventoryTransHistory.setTransId(TransactionNames.LOT_RETURN_KEY);
                } else {
                    inventoryTransHistory.setTransId(TransactionNames.LOT_CONSUME_KEY);
                }
                inventoryTransHistory.setTransQty(issueQty);
                inventoryTransHistory.setTransDate(transactionLog.getTransStartTimestamp());
                inventoryTransHistory.setFacilityRrn(facilityRrn);

                inventoryTransHistory.setWarehouseId(lotInventory.getWarehouseId());
                inventoryTransHistory.setWarehouseRrn(lotInventory.getWarehouseRrn());
                inventoryTransHistory.setMaterialLotNumber(lotInventory.getLotNumber());
                inventoryTransHistory.setItemRrn(lotInventory.getItemRrn());

                inventoryTransHistory.setLotRrn(lotRrn);
                inventoryTransHistory.setStepSequence(lotStepSequence);

                inventoryTransHistory.setComments(lotId);

                inventoryTransHistory.setLotBox(lotBox);

                saveConsumeMaterialFromWarehouse(lotInventory, inventoryTransHistory);
            }

        }

        @Override
        public void saveConsumeMaterialFromWarehouse(LotInventoryDO lotInventory,
                                                     InventoryTransHistoryDO inventoryTransHistory) {
            saveMaterialForConsumed(inventoryTransHistory);

            saveWarehouseForConsumed(inventoryTransHistory);

            saveLotInventoryForConsumed(lotInventory, inventoryTransHistory);
        }

        @Override
        public void saveMaterialForConsumed(InventoryTransHistoryDO inventoryTransHistory) {
            materialDAO.updateMaterialForIssueQty(inventoryTransHistory.getItemRrn(), inventoryTransHistory.getTransQty());
            materialDAO.insertMaterialHistory(inventoryTransHistory.getItemRrn(), inventoryTransHistory.getTransRrn(),
                                              inventoryTransHistory.getTransSequence(),
                                              inventoryTransHistory.getTransQty());
        }

        @Override
        public List<Map<String, Object>> getLotInventoryTransHistory(Long transRrn) {
            return lotInventoryDAO.getLotInventoryTransHistory(transRrn);

        }

        private void saveWarehouseForConsumed(InventoryTransHistoryDO inventoryTransHistory) {
            warehouseDAO.updateWarehouseInventoryForIssueQty(inventoryTransHistory.getWarehouseRrn(),
                                                             inventoryTransHistory.getItemRrn(),
                                                             inventoryTransHistory.getTransQty());
            warehouseDAO.insertWarehouseInventoryHistory(inventoryTransHistory.getWarehouseRrn(),
                                                         inventoryTransHistory.getItemRrn(),
                                                         inventoryTransHistory.getTransRrn(),
                                                         inventoryTransHistory.getTransSequence(),
                                                         inventoryTransHistory.getTransQty());
        }

        private void saveLotInventoryForConsumed(LotInventoryDO lotInventory,
                                                 InventoryTransHistoryDO inventoryTransHistory) {
            lotInventoryDAO.updateLotInventoryForQty(lotInventory);
            warehouseDAO.insertInventoryTransHistory(inventoryTransHistory);
            warehouseDAO.insertInventoryTransHistoryExt(inventoryTransHistory);
        }

        @Override
        public void insertLotConsumesMaterialHistory(LotConsumesMaterialHistory lotConsumesMaterialHistory) {
            lotInventoryDAO.insertLotConsumesMaterialHistory(lotConsumesMaterialHistory);
        }

        @Override
        public List<Map<String, Object>> getMaterialInfoByLot(long lotRrn) {
            return lotInventoryDAO.getMaterialInfoByLot(lotRrn);
        }

        @Override
        public Map<String, Object> getMaterialInfoByUnit(long unitRrn) {
            return lotInventoryDAO.getMaterialInfoByUnit(unitRrn);
        }

        @Override
        public String getReturnMaterialLotNumber(Long itemRrn, long warehouseRrn, String lotNumber, String orderId) {
            return lotInventoryDAO.getReturnMaterialLotNumber(itemRrn, warehouseRrn, lotNumber, orderId);
        }

        @Override
        public List<LotInventoryDO> getLotInventoryList4Erp(Long itemRrn, Long warehouseRrn, String lotNumber) {
            return lotInventoryDAO.getLotInventoryList4Erp(itemRrn, warehouseRrn, lotNumber);
        }

        @Override
        public List<LotInventoryDO> getAvailableLotInventory(long itemRrn, long warehouseRrn, String lotNumber) {
            return lotInventoryDAO.getAvailableLotInventory(itemRrn, warehouseRrn, lotNumber);
        }

        @Override
        public List<LotInventoryDO> getLotInventoryListByLotNumberLike(long itemRrn, long warehouseRrn, String lotNumber) {
            return lotInventoryDAO.getLotInventoryListByLotNumberLike(itemRrn, warehouseRrn, lotNumber);
        }

        @Override
        public String getReturnMaterialLotNumberForBom(Long itemRrn, long warehouseRrn, String lotNumber) {
            return lotInventoryDAO.getReturnMaterialLotNumberForBom(itemRrn, warehouseRrn, lotNumber);
        }

    }