# WarehouseDAOImpl.java

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

    import com.mycim.framework.jdbc.JdbcTemplate;
    import com.mycim.framework.jdbc.Page;
    import com.mycim.framework.jdbc.mapper.RowMapper;
    import com.mycim.framework.utils.MiscUtils;
    import com.mycim.framework.utils.lang.StringUtils;
    import com.mycim.framework.utils.lang.collections.MapUtils;
    import com.mycim.server.asm.dao.WarehouseDAO;
    import com.mycim.server.asm.dao.mapper.LotConsumesMaterialHistoryRowMapper;
    import com.mycim.server.asm.dao.mapper.WarehouseInventoryDORowMapper;
    import com.mycim.valueobject.consts.DataBaseNames;
    import com.mycim.valueobject.inv.InventoryTransHistoryDO;
    import com.mycim.valueobject.inv.WarehouseInventoryDO;
    import com.mycim.valueobject.prp.Item;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.support.rowset.SqlRowSet;
    import org.springframework.stereotype.Repository;

    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Timestamp;
    import java.sql.Types;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;

    /**
     * @author shijie.deng
     * @date 2019/8/27
     **/
    @Repository
    public class WarehouseDAOImpl implements WarehouseDAO {

        @Autowired
        JdbcTemplate jdbcTemplate;

        @Override
        public List<WarehouseInventoryDO> getWarehouseInventoryListForMaterial(Long warehouseRrn,
                                                                               Map<String, String> condition) {
            StringBuilder sql = new StringBuilder("SELECT ");

            sql.append(" li.ITEM_RRN, li.WAREHOUSE_RRN, li.WAREHOUSE_ID, ");
            sql.append(" SUM(li.RECEIPT_QTY) AS RECEIPT_QTY, SUM(li.ISSUE_QTY) AS ISSUE_QTY, SUM(li.ADJUST_QTY) AS" + " " +
                               "ADJUST_QTY, ");
            sql.append(" (SUM(li.RECEIPT_QTY) + SUM(li.ADJUST_QTY) - SUM(li.ISSUE_QTY)) AS TOTAL_QTY ");
            sql.append(" FROM LOT_INVENTORY li, ITEM i, NAMED_OBJECT ino ");
            sql.append(
                    " WHERE li.ITEM_RRN = i.ITEM_RRN AND i.ITEM_RRN = ino.INSTANCE_RRN AND li.LOT_NUMBER NOT " + "LIKE " +
                            "'%#$#RETURN' ");
            sql.append(" AND li.WAREHOUSE_RRN = ? ");

            String tempString = MapUtils.getString(condition, "materialRrn");
            if (StringUtils.isNotEmpty(tempString)) {
                sql.append(" AND li.ITEM_RRN = '").append(tempString).append("' ");
            }

            tempString = MapUtils.getString(condition, "materialClass");
            if (StringUtils.isNotEmpty(tempString)) {
                sql.append(" AND i.ITEM_CLASS = '").append(tempString).append("' ");
            }

            tempString = MapUtils.getString(condition, "materialType");
            if (StringUtils.isNotEmpty(tempString)) {
                sql.append(" AND ino.OBJECT_SUBTYPE = '").append(tempString).append("' ");
            }

            tempString = MapUtils.getString(condition, "transType");
            if (StringUtils.isNotEmpty(tempString)) {
                sql.append(" AND li.LOT_NUMBER LIKE '%").append(tempString).append("' ");
            }

            sql.append(" GROUP BY li.ITEM_RRN, li.WAREHOUSE_RRN, li.WAREHOUSE_ID ");
            sql.append(" ORDER BY li.ITEM_RRN ");

            return jdbcTemplate.query(sql.toString(), new Object[]{warehouseRrn}, new RowMapper<WarehouseInventoryDO>() {

                @Override
                public WarehouseInventoryDO mapRow(ResultSet rs, int rowNum) throws SQLException {
                    WarehouseInventoryDO warehouseInventoryDO = new WarehouseInventoryDO();

                    warehouseInventoryDO.setItemRrn(rs.getLong("ITEM_RRN"));
                    warehouseInventoryDO.setWarehouseRrn(rs.getLong("WAREHOUSE_RRN"));
                    warehouseInventoryDO.setWarehouseId(rs.getString("WAREHOUSE_ID"));
                    warehouseInventoryDO.setOpeningBalance(rs.getDouble("TOTAL_QTY"));
                    warehouseInventoryDO.setReceiptQty(rs.getDouble("RECEIPT_QTY"));
                    warehouseInventoryDO.setIssueQty(rs.getDouble("ISSUE_QTY"));
                    warehouseInventoryDO.setAdjustQty(rs.getDouble("ADJUST_QTY"));

                    return warehouseInventoryDO;
                }
            });
        }

        @Override
        public List<WarehouseInventoryDO> getWarehouseInventoryListForMaterialWithExt(Long warehouseRrn,
                                                                                      Map<String, String> condition) {
            List<Object> args = new ArrayList<>();
            StringBuilder sql = new StringBuilder("SELECT ");

            sql.append(" li.ITEM_RRN, li.WAREHOUSE_RRN, li.WAREHOUSE_ID, ")
               .append(" SUM(li.RECEIPT_QTY) AS RECEIPT_QTY, SUM(li.ISSUE_QTY) AS")
               .append(" ISSUE_QTY, SUM(li.ADJUST_QTY) AS ADJUST_QTY, ")
               .append(" (SUM(li.RECEIPT_QTY) + SUM(li.ADJUST_QTY) - SUM(li.ISSUE_QTY)) AS TOTAL_QTY ")
               .append(" FROM LOT_INVENTORY li, LOT_INVENTORY_EXT lie, ITEM i, NAMED_OBJECT ino ")
               .append(" WHERE li.ITEM_RRN = i.ITEM_RRN AND i.ITEM_RRN = ino.INSTANCE_RRN")
               .append(" AND li.LOT_NUMBER NOT LIKE '%#$#RETURN' ")
               .append(" AND li.ITEM_RRN=lie.ITEM_RRN AND li.LOT_NUMBER=lie.LOT_NUMBER")
               .append(" AND li.WAREHOUSE_RRN=lie.WAREHOUSE_RRN ")
               .append(" AND li.WAREHOUSE_RRN = ? ");
            args.add(warehouseRrn);
            String tempString = MapUtils.getString(condition, "materialRrn");
            if (StringUtils.isNotEmpty(tempString)) {
                sql.append(" AND li.ITEM_RRN = ? ");
                args.add(tempString);
            }

            if (StringUtils.isNotEmpty(tempString = MapUtils.getString(condition, "materialClass"))) {
                sql.append(" AND i.ITEM_CLASS = ? ");
                args.add(tempString);
            }

            if (StringUtils.isNotEmpty(tempString = MapUtils.getString(condition, "materialType"))) {
                sql.append(" AND ino.OBJECT_SUBTYPE = ? ");
                args.add(tempString);
            }

            if (StringUtils.isNotEmpty(tempString = MapUtils.getString(condition, "transType"))) {
                sql.append(" AND li.LOT_NUMBER LIKE ? ");
                args.add("%" + tempString);
            }

            if (StringUtils.isNotEmpty(tempString = MapUtils.getString(condition, "FROM_TYPE"))){
                sql.append(" AND LIE.ATTRIBUTE_DATA2 = ? ");
                args.add(tempString);
            }

            if (StringUtils.isNotBlank(tempString = MapUtils.getString(condition, "lotNumber"))){
                sql.append(" AND LI.LOT_NUMBER = ? ");
                args.add(tempString);
            }

            sql.append(" GROUP BY li.ITEM_RRN, li.WAREHOUSE_RRN, li.WAREHOUSE_ID ");
            sql.append(" ORDER BY li.ITEM_RRN ");

            return jdbcTemplate.query(sql.toString(), args.toArray(),
                                      (RowMapper<WarehouseInventoryDO>) (rs, rowNum) -> {
                                          WarehouseInventoryDO warehouseInventoryDO = new WarehouseInventoryDO();
                                          warehouseInventoryDO.setItemRrn(rs.getLong("ITEM_RRN"));
                                          warehouseInventoryDO.setWarehouseRrn(rs.getLong("WAREHOUSE_RRN"));
                                          warehouseInventoryDO.setWarehouseId(rs.getString("WAREHOUSE_ID"));
                                          warehouseInventoryDO.setOpeningBalance(rs.getDouble("TOTAL_QTY"));
                                          warehouseInventoryDO.setReceiptQty(rs.getDouble("RECEIPT_QTY"));
                                          warehouseInventoryDO.setIssueQty(rs.getDouble("ISSUE_QTY"));
                                          warehouseInventoryDO.setAdjustQty(rs.getDouble("ADJUST_QTY"));
                                          return warehouseInventoryDO;
                                      });
        }

        @Override
        public Boolean checkMaterialIsExistedInWarehouse(Long warehouseRrn, Long materialRrn) {
            StringBuilder sql = new StringBuilder("SELECT ");
            sql.append(" NVL(COUNT(*), 0) ");
            sql.append(" FROM ");
            sql.append(" (SELECT ITEM_RRN FROM ").append(DataBaseNames.WAREHOUSE_INVENTORY);
            sql.append(" WHERE ITEM_RRN = ? AND WAREHOUSE_RRN = ? and rownum = 1 ) temp_1");
            Object[] args = new Object[]{materialRrn, warehouseRrn};
            return jdbcTemplate.queryForObject(sql.toString(), args, Boolean.class);
        }

        @Override
        public void updateWarehouseInventoryForReceiptQty(Long warehouseRrn, Long itemRrn, Double receiptQty) {
            updateWarehouseInventoryForQty(warehouseRrn, itemRrn, receiptQty, 0D, 0D);
        }

        @Override
        public void insertWarehouseInventory(WarehouseInventoryDO warehouseInventory) {
            StringBuilder sql = new StringBuilder("INSERT INTO ");

            sql.append(DataBaseNames.WAREHOUSE_INVENTORY);
            sql.append(" (ITEM_RRN, WAREHOUSE_RRN, WAREHOUSE_ID, ");
            sql.append(" OPENING_BALANCE, RECEIPT_QTY, ISSUE_QTY, ADJUST_QTY, ");
            sql.append(" QUANTITY_OF_WARNING, WARNING_ALARM_ID) ");
            sql.append(" VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) ");

            Object[] args = new Object[]{warehouseInventory.getItemRrn(), warehouseInventory.getWarehouseRrn(),
                    warehouseInventory.getWarehouseId(), warehouseInventory.getOpeningBalance(),
                    warehouseInventory.getReceiptQty(), warehouseInventory.getIssueQty(),
                    warehouseInventory.getAdjustQty(), warehouseInventory.getQuantityOfWarning(),
                    warehouseInventory.getWarningAlarmId()};

            jdbcTemplate.update(sql.toString(), args);
        }

        @Override
        public void insertWarehouseInventoryHistory(Long warehouseRrn, Long itemRrn, Long transRrn, Long transSequence,
                                                    Double transQty) {
            StringBuilder sql = new StringBuilder("INSERT INTO ");

            sql.append(DataBaseNames.WAREHOUSE_INVENTORY_H);
            sql.append(" (ITEM_RRN, WAREHOUSE_RRN, WAREHOUSE_ID, ");
            sql.append(" OPENING_BALANCE, RECEIPT_QTY, ISSUE_QTY, ADJUST_QTY, ");
            sql.append(" QUANTITY_OF_WARNING, WARNING_ALARM_ID, TRANS_RRN, TRANS_SEQUENCE, TRANS_QTY) ");
            sql.append(" SELECT ");
            sql.append(" ITEM_RRN, WAREHOUSE_RRN, WAREHOUSE_ID, ");
            sql.append(" OPENING_BALANCE, RECEIPT_QTY, ISSUE_QTY, ADJUST_QTY, ");
            sql.append(" QUANTITY_OF_WARNING, WARNING_ALARM_ID, ");
            sql.append(transRrn).append(", ").append(transSequence).append(", ").append(transQty);
            sql.append(" FROM ").append(DataBaseNames.WAREHOUSE_INVENTORY);
            sql.append(" WHERE ITEM_RRN = ? AND WAREHOUSE_RRN = ? ");

            jdbcTemplate.update(sql.toString(), itemRrn, warehouseRrn);
        }

        @Override
        public void insertInventoryTransHistory(InventoryTransHistoryDO inventoryTransHistory) {
            StringBuilder sql = new StringBuilder("INSERT INTO ");

            sql.append(DataBaseNames.INVENTORY_TRANS_HISTORY);
            sql.append(
                    " (TRANS_RRN, TRANS_SEQUENCE, ITEM_RRN, MATERIAL_LOT_NUMBER, FACILITY_RRN, TRANS_ID, " + "TRANS_QTY, " +
                            "TRANS_DATE, ");
            sql.append(
                    " WAREHOUSE_RRN, WAREHOUSE_ID, LOCATION_RRN, LOCATION_ID, CUSTOMER_RRN, CUSTOMER_ID, " + "VENDOR_RRN," +
                            " VENDOR_ID, ");
            sql.append(" ORDER_NUMBER, TICKET_NUMBER, CHECKLIST_JOB_RRN, RUN_RRN, LOT_RRN, COMMENTS, ");
            sql.append(" QTY1, QTY2, BOR_RRN, BOR_VERSION, REASON_CODE, STEP_SEQUENCE,BATCH_ID) ");
            sql.append(
                    " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " + "?,? ) ");

            Object[] args = new Object[]{inventoryTransHistory.getTransRrn(), inventoryTransHistory.getTransSequence(),
                    inventoryTransHistory.getItemRrn(), inventoryTransHistory.getMaterialLotNumber(),
                    inventoryTransHistory.getFacilityRrn(), inventoryTransHistory.getTransId(),
                    inventoryTransHistory.getTransQty(), inventoryTransHistory.getTransDate(),
                    inventoryTransHistory.getWarehouseRrn(), inventoryTransHistory.getWarehouseId(),
                    inventoryTransHistory.getLocationRrn(), inventoryTransHistory.getLocationId(),
                    inventoryTransHistory.getCustomerRrn(), inventoryTransHistory.getCustomerId(),
                    inventoryTransHistory.getVendorRrn(), inventoryTransHistory.getVendorId(),
                    inventoryTransHistory.getOrderNumber(), inventoryTransHistory.getTicketNumber(),
                    inventoryTransHistory.getChecklistJobRrn(), inventoryTransHistory.getRunRrn(),
                    inventoryTransHistory.getLotRrn(), inventoryTransHistory.getComments(),
                    inventoryTransHistory.getQty1(), inventoryTransHistory.getQty2(), inventoryTransHistory.getBorRrn(),
                    inventoryTransHistory.getBorVersion(), inventoryTransHistory.getReasonCode(),
                    inventoryTransHistory.getStepSequence(),inventoryTransHistory.getBatchId()};

            jdbcTemplate.update(sql.toString(), args);
        }

        @Override
        public void insertInventoryTransHistoryExt(InventoryTransHistoryDO inventoryTransHistory) {
            StringBuilder sql = new StringBuilder("INSERT INTO ");

            sql.append(DataBaseNames.INVENTORY_TRANS_HISTORY_EXT);
            sql.append(" (TRANS_RRN, TRANS_SEQUENCE, MATERIAL_LOT_NUMBER, ITEM_RRN, WAREHOUSE_RRN, ");
            sql.append(" LOT_BOX,PRODUCTION_DATE,INCOMING_DATE,CHECK_DATE,CHECK_USER,CHECK_RESULT, " + "ATTRIBUTE_DATA1, " +
                               "ATTRIBUTE_DATA2, ATTRIBUTE_DATA3, ATTRIBUTE_DATA4, ATTRIBUTE_DATA5) ");
            sql.append(" VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?,?,?,? ) ");

            Object[] args = new Object[]{inventoryTransHistory.getTransRrn(), inventoryTransHistory.getTransSequence(),
                    inventoryTransHistory.getMaterialLotNumber(), inventoryTransHistory.getItemRrn(),
                    inventoryTransHistory.getWarehouseRrn(), inventoryTransHistory.getLotBox(),
                    inventoryTransHistory.getProductionDate(), inventoryTransHistory.getIncomingDate(),
                    inventoryTransHistory.getCheckDate(), inventoryTransHistory.getCheckUser(),
                    inventoryTransHistory.getCheckResult(), inventoryTransHistory.getAttributeData1(),
                    inventoryTransHistory.getAttributeData2(), inventoryTransHistory.getAttributeData3(),
                    inventoryTransHistory.getAttributeData4(), inventoryTransHistory.getAttributeData5()};

            jdbcTemplate.update(sql.toString(), args);
        }

        @Override
        public WarehouseInventoryDO getWarehouseInventory(Long warehouseRrn, Long materialRrn) {
            StringBuilder sql = new StringBuilder("SELECT ");

            sql.append(" ITEM_RRN, WAREHOUSE_RRN, WAREHOUSE_ID, ");
            sql.append(" OPENING_BALANCE, RECEIPT_QTY, ISSUE_QTY, ADJUST_QTY, ");
            sql.append(" QUANTITY_OF_WARNING, WARNING_ALARM_ID ");
            sql.append(" FROM ").append(DataBaseNames.WAREHOUSE_INVENTORY);
            sql.append(" WHERE ITEM_RRN = ? AND WAREHOUSE_RRN = ? ");

            return jdbcTemplate.queryForObject(sql.toString(), new Object[]{materialRrn, warehouseRrn},
                                               new WarehouseInventoryDORowMapper());
        }

        @Override
        public void updateWarehouseInventoryForIssueQty(Long warehouseRrn, Long itemRrn, Double issueQty) {
            updateWarehouseInventoryForQty(warehouseRrn, itemRrn, 0D, issueQty, 0D);
        }

        @Override
        public void updateWarehouseInventoryForAdjustQty(Long warehouseRrn, Long itemRrn, Double adjustQty) {
            updateWarehouseInventoryForQty(warehouseRrn, itemRrn, 0D, 0D, adjustQty);
        }

        @Override
        public Page getInventoryTransHistoryForPage(Page page, Long warehouseRrn, Long materialRrn, String lotNumber,
                                                    String transId, Timestamp startDateTime, Timestamp endDateTime) {
            StringBuilder sql = new StringBuilder("SELECT ");

            sql.append(" io.INSTANCE_ID, io.INSTANCE_DESC, ih.MATERIAL_LOT_NUMBER, ih.TRANS_ID, ih.TRANS_QTY, ih" +
                               ".TRANS_DATE, ");
            sql.append(" ih.WAREHOUSE_ID, ih.LOCATION_ID, ih.CUSTOMER_ID, ih.VENDOR_ID, ");
            sql.append(
                    " ih.ORDER_NUMBER, ih.TICKET_NUMBER, ih.CHECKLIST_JOB_RRN, ih.RUN_RRN, ih.LOT_RRN, ih" + ".COMMENTS, ");
            sql.append(" ih.QTY1, ih.QTY2, ih.BOR_RRN, ih.BOR_VERSION, ih.REASON_CODE, ih.STEP_SEQUENCE, tl" +
                               ".TRANS_PERFORMED_BY ");
            sql.append(" FROM ");
            sql.append(DataBaseNames.INVENTORY_TRANS_HISTORY).append(" ih, ");
            sql.append(DataBaseNames.TRANSACTION_LOG).append(" tl, ");
            sql.append(DataBaseNames.NAMEDOBJECT).append(" io ");
            sql.append(" WHERE ih.TRANS_RRN = tl.TRANS_RRN AND ih.ITEM_RRN = io.INSTANCE_RRN ");
            sql.append(" AND ih.WAREHOUSE_RRN = ? ");

            List<Object> args = new ArrayList<>();
            args.add(warehouseRrn);

            if (materialRrn != null && materialRrn > 0) {
                sql.append(" AND ih.ITEM_RRN = ? ");
                args.add(materialRrn);
            }

            if (StringUtils.isNotEmpty(lotNumber)) {
                sql.append(" AND ih.MATERIAL_LOT_NUMBER = ? ");
                args.add(lotNumber);
            }

            if (StringUtils.isNotEmpty(transId)) {
                sql.append(" AND ih.TRANS_ID = ? ");
                args.add(transId);
            }

            if (startDateTime != null) {
                sql.append(" AND ih.TRANS_DATE > ? ");
                args.add(startDateTime);
            }

            if (endDateTime != null) {
                sql.append(" AND ih.TRANS_DATE < ? ");
                args.add(endDateTime);
            }

            sql.append(" ORDER BY ih.TRANS_DATE DESC, ih.TRANS_SEQUENCE ");

            return jdbcTemplate.queryForPage(page, sql.toString(), args.toArray(), new RowMapper<Map<String, String>>() {

                @Override
                public Map<String, String> mapRow(ResultSet rs, int rowNum) throws SQLException {
                    Map<String, String> map = new HashMap<>();

                    map.put("materialId", rs.getString("INSTANCE_ID"));
                    map.put("materialDesc", rs.getString("INSTANCE_DESC"));
                    map.put("lotNumber", rs.getString("MATERIAL_LOT_NUMBER"));
                    map.put("transType", rs.getString("TRANS_ID"));
                    //map.put("transQty",Double.toString(rs.getDouble
                    // ("TRANS_QTY")));
                    map.put("transQty", Long.toString(Math.abs(rs.getLong("TRANS_QTY"))));
                    map.put("transDate", rs.getString("TRANS_DATE"));
                    map.put("operator", rs.getString("TRANS_PERFORMED_BY"));
                    map.put("comments", rs.getString("COMMENTS"));

                    return map;
                }
            });
        }

        @Override
        public Item getItem(Long itemRrn) {
            String sql = "SELECT ITEM_RRN,ITEM_EXTEND_NUMBER,ITEM_CLASS," + "DEFAULT_WAREHOUSE_RRN,DEFAULT_LOCATION_RRN," +
                    "OPENING_BALANCE," + "RECEIPT_QTY,ISSUE_QTY,ADJUST_QTY,STORE_UOM,PURCHASE_UOM," + "SALES_UOM," +
                    "LOT_TRACKING_FLAG,PRODUCT_FAMILY_RRN," + "SUBPRODUCT_FLAG,PRODUCT_ENGINEER_RRN,HOLD_ON_LOW_YIELD" +
                    " FROM " + DataBaseNames.ITEM + " WHERE ITEM_RRN = ?";

            return jdbcTemplate.queryForObject(sql, new RowMapper<Item>() {
                @Override
                public Item mapRow(ResultSet resultSet, int rowNum) throws SQLException {
                    Item item = new Item();
                    item.setItemExtendNumber(resultSet.getString("ITEM_EXTEND_NUMBER"));
                    item.setItemClass(resultSet.getString("ITEM_CLASS"));
                    item.setDefaultWarehouseRrn(resultSet.getLong("DEFAULT_WAREHOUSE_RRN"));
                    item.setDefaultLocationRrn(resultSet.getLong("DEFAULT_LOCATION_RRN"));
                    item.setOpeningBalance(resultSet.getDouble("OPENING_BALANCE"));
                    item.setReceiptQty(resultSet.getDouble("RECEIPT_QTY"));
                    item.setIssueQty(resultSet.getDouble("ISSUE_QTY"));
                    item.setAdjustQty(resultSet.getDouble("ADJUST_QTY"));
                    item.setStoreUom(resultSet.getString("STORE_UOM"));
                    item.setPurchaseUom(resultSet.getString("PURCHASE_UOM"));
                    item.setSalesUom(resultSet.getString("SALES_UOM"));
                    item.setLotTrackingFlag(resultSet.getString("LOT_TRACKING_FLAG"));
                    item.setProductFamilyRrn((resultSet.getLong("PRODUCT_FAMILY_RRN")));
                    item.setSubproductFlag(resultSet.getString("SUBPRODUCT_FLAG"));
                    item.setProductEngineerRrn(resultSet.getLong("PRODUCT_ENGINEER_RRN"));
                    item.setHoldOnLowYield(resultSet.getDouble("HOLD_ON_LOW_YIELD"));
                    return item;
                }
            }, itemRrn);
        }

        @Override
        public void increaseItemQty(Double receiptQty, Double issueQty, Double adjustQty, Long itemRrn) {
            if (receiptQty == null) {
                receiptQty = (double) 0;
            }

            if (issueQty == null) {
                issueQty = (double) 0;
            }

            if (adjustQty == null) {
                adjustQty = (double) 0;
            }

            assert itemRrn != null;

            String sql =
                    "UPDATE " + DataBaseNames.ITEM + " SET " + " receipt_qty = NVL(receipt_qty,0) + " + receiptQty + "," +
                            " issue_qty = NVL(issue_qty,0) + " + issueQty + "," + " adjust_qty = NVL(adjust_qty,0) + " +
                            adjustQty + " WHERE item_rrn = " + itemRrn;

            jdbcTemplate.update(sql);

        }

        @Override
        public void increaseWareHouseInventory(Long itemRrn, Long warehouseRrn, String warehouseId, Double openingBalance,
                                               Double receiptQty, Double issueQty, Double adjustQty) {
            if (receiptQty == null) {
                receiptQty = (double) 0;
            }

            if (issueQty == null) {
                issueQty = (double) 0;
            }

            if (adjustQty == null) {
                adjustQty = (double) 0;
            }
            String sql;

            if (this.itemIsExistedInWarehouse(itemRrn, warehouseRrn)) {
                sql = "UPDATE " + DataBaseNames.WAREHOUSE_INVENTORY + " SET " + " receipt_qty = NVL(receipt_qty,0) + " +
                        receiptQty + "," + " issue_qty = NVL(issue_qty,0) + " + issueQty + "," +
                        " adjust_qty = NVL(adjust_qty,0) + " + adjustQty + " WHERE  item_rrn = " + itemRrn + " AND " +
                        " warehouse_rrn = " + warehouseRrn;
            } else {
                Object[] obj = {itemRrn, warehouseRrn, warehouseId, openingBalance, receiptQty, issueQty, adjustQty};
                sql = "INSERT INTO " + DataBaseNames.WAREHOUSE_INVENTORY + " ( item_rrn, warehouse_rrn, warehouse_id, " +
                        "opening_balance, receipt_qty, issue_qty, " + "adjust_qty) " + " VALUES (" +
                        MiscUtils.parseSQL(obj) + ")";
            }

            jdbcTemplate.update(sql);

        }

        @Override
        public void createInventoryTransactionHistory(long transRrn, long transSequence, Long itemRrn,
                                                      String materialLotNumber, Long facilityRrn, String transId,
                                                      Double transQty, Timestamp transDate, Long warehouseRrn,
                                                      String warehouseId, Long locationRrn, String locationId,
                                                      Long customerRrn, String customerId, Long vendorRrn, String vendorId,
                                                      String orderNumber, String ticketNumber, Long checklistJobRrn,
                                                      Long lotRrn, Long stepSequence, String comments) {
            String sql = "INSERT INTO INVENTORY_TRANS_HISTORY (TRANS_RRN," + "TRANS_SEQUENCE,ITEM_RRN," +
                    "MATERIAL_LOT_NUMBER,FACILITY_RRN," + "TRANS_ID,TRANS_QTY,TRANS_DATE,WAREHOUSE_RRN,WAREHOUSE_ID," +
                    "LOCATION_RRN,LOCATION_ID,CUSTOMER_RRN,CUSTOMER_ID," + "VENDOR_RRN,VENDOR_ID,ORDER_NUMBER," +
                    "TICKET_NUMBER," + "CHECKLIST_JOB_RRN,RUN_RRN,LOT_RRN,COMMENTS) " + " VALUES (?, ?, ?, ?, ?, ?, ?, ?," +
                    " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

            List<Object> args = new ArrayList<>();
            args.add(transRrn);
            args.add(transSequence);

            args.add(itemRrn == null ? Types.BIGINT : itemRrn);

            args.add(materialLotNumber);

            args.add(facilityRrn == null ? Types.BIGINT : facilityRrn);

            args.add(transId);

            args.add(transQty == null ? Types.DOUBLE : transQty);

            args.add(transDate);

            args.add(warehouseRrn == null ? Types.BIGINT : warehouseRrn);

            args.add(warehouseId);

            args.add(locationRrn == null ? Types.BIGINT : locationRrn);

            args.add(locationId);

            args.add(customerRrn == null ? Types.BIGINT : customerRrn);

            args.add(customerId);

            args.add(vendorRrn == null ? Types.BIGINT : vendorRrn);

            args.add(vendorId);
            args.add(orderNumber);
            args.add(ticketNumber);

            args.add(checklistJobRrn == null ? Types.BIGINT : checklistJobRrn);
            args.add(stepSequence == null ? Types.BIGINT : stepSequence);
            args.add(lotRrn == null ? Types.BIGINT : lotRrn);

            args.add(comments);

            jdbcTemplate.update(sql, args.toArray());
        }

        @Override
        public Page getLotConsumesMaterialHistoryForPage(Page page, Map<String, Object> conditions) {
            StringBuilder sql = new StringBuilder("SELECT ");

            sql.append(" TRANS_RRN, TRANS_SEQUENCE, BOR_RRN, BOR_VERSION, BOR_RESOURCE_SEQ, BOR_LOSS_TYPE, " +
                               "BOR_BASIS_CODE, ");
            sql.append(" LOT_NUMBER, ITEM_RRN, WAREHOUSE_RRN, MATERIAL_TYPE, RUN_RRN, LOT_RRNS, LOT_IDS, ");
            sql.append(" CONSUMPTION_QTY, CONSUMPTION_DATE, CONSUMPRION_USER_ID ");
            sql.append(" FROM LOT_CONSUMES_MATERIAL_HISTORY ");
            sql.append(" WHERE 1 = 1 ");

            List<Object> args = new ArrayList<>();

            if (conditions.get("borRrn") != null) {
                sql.append(" AND BOR_RRN = ? ");
                args.add(conditions.get("borRrn"));
            }

            if (conditions.get("borVersion") != null) {
                sql.append(" AND BOR_VERSION = ? ");
                args.add(conditions.get("borVersion"));
            }

            if (conditions.get("borLossType") != null) {
                sql.append(" AND BOR_LOSS_TYPE = ? ");
                args.add(conditions.get("borLossType"));
            }

            if (conditions.get("materialRrn") != null) {
                sql.append(" AND ITEM_RRN = ? ");
                args.add(conditions.get("materialRrn"));
            }

            if (conditions.get("warehouseRrn") != null) {
                sql.append(" AND WAREHOUSE_RRN = ? ");
                args.add(conditions.get("warehouseRrn"));
            }

            if (conditions.get("lotId") != null) {
                sql.append(" AND LOT_IDS LIKE ? ");
                args.add("%" + conditions.get("lotId") + "%");
            }

            if (conditions.get("lotStepSequence") != null) {
                sql.append(" AND LOT_IDS LIKE ? ");
                args.add("%(" + conditions.get("lotStepSequence") + ")%");
            }

            if (conditions.get("startDateTime") != null) {
                sql.append(" AND CONSUMPTION_DATE > ? ");
                args.add(conditions.get("startDateTime"));
            }

            if (conditions.get("endDateTime") != null) {
                sql.append(" AND CONSUMPTION_DATE < ? ");
                args.add(conditions.get("endDateTime"));
            }

            //todo：该sql用TRANS_RRN进行排序
            sql.append(" ORDER BY TRANS_RRN DESC, TRANS_SEQUENCE DESC ");

            return jdbcTemplate
                    .queryForPage(page, sql.toString(), args.toArray(), new LotConsumesMaterialHistoryRowMapper());
        }

        @Override
        public Page getReceiveHistoryForPage(Page page, Long warehouseRrn, Long materialRrn, String lotNumber,
                                             Timestamp startDateTime, Timestamp endDateTime) {
            StringBuilder sql = new StringBuilder("SELECT ");

            sql.append(" io.INSTANCE_ID, io.INSTANCE_DESC, ih.MATERIAL_LOT_NUMBER, ih.TRANS_ID, ih.TRANS_QTY, ih" +
                               ".TRANS_DATE, ");
            sql.append(" ih.WAREHOUSE_ID, ih.LOCATION_ID, ih.CUSTOMER_ID, ih.VENDOR_ID, ");
            sql.append(
                    " ih.ORDER_NUMBER, ih.TICKET_NUMBER, ih.CHECKLIST_JOB_RRN, ih.RUN_RRN, ih.LOT_RRN, ih" + ".COMMENTS, ");
            sql.append(" ih.QTY1, ih.QTY2, ih.BOR_RRN, ih.BOR_VERSION, ih.REASON_CODE, ih.STEP_SEQUENCE, tl" +
                               ".TRANS_PERFORMED_BY ");
            sql.append(" FROM ");
            sql.append(DataBaseNames.INVENTORY_TRANS_HISTORY).append(" ih, ");
            sql.append(DataBaseNames.TRANSACTION_LOG).append(" tl, ");
            sql.append(DataBaseNames.NAMEDOBJECT).append(" io ");
            sql.append(" WHERE ih.TRANS_RRN = tl.TRANS_RRN AND ih.ITEM_RRN = io.INSTANCE_RRN ");
            sql.append(" AND ih.WAREHOUSE_RRN = ? AND ih.TRANS_ID = 'RECEIVE'");
            List<Object> args = new ArrayList<>();
            args.add(warehouseRrn);
            if (materialRrn != null && materialRrn > 0) {
                sql.append(" AND ih.ITEM_RRN = ? ");
                args.add(materialRrn);
            }
            if (StringUtils.isNotEmpty(lotNumber)) {
                sql.append(" AND ih.MATERIAL_LOT_NUMBER = ? ");
                args.add(lotNumber);
            }

            if (startDateTime != null) {
                sql.append(" AND ih.TRANS_DATE > ? ");
                args.add(startDateTime);
            }

            if (endDateTime != null) {
                sql.append(" AND ih.TRANS_DATE < ? ");
                args.add(endDateTime);
            }

            sql.append(" ORDER BY ih.TRANS_DATE DESC, ih.TRANS_SEQUENCE ");

            return jdbcTemplate
                    .queryForPage(page, sql.toString(), args.toArray(), (RowMapper<Map<String, String>>) (rs, rowNum) -> {
                        Map<String, String> map = new HashMap<>();
                        map.put("materialId", rs.getString("INSTANCE_ID"));
                        String maerialDesc =
                                rs.getString("INSTANCE_DESC") != null ? rs.getString("INSTANCE_DESC") : StringUtils.EMPTY;
                        map.put("materialDesc", maerialDesc);
                        map.put("lotNumber", rs.getString("MATERIAL_LOT_NUMBER"));
                        map.put("transQty", Integer.toString(Math.abs(rs.getInt("TRANS_QTY"))));
                        map.put("transDate", rs.getString("TRANS_DATE"));
                        map.put("operator", rs.getString("TRANS_PERFORMED_BY"));
                        String comments = rs.getString("COMMENTS") != null ? rs.getString("COMMENTS") : StringUtils.EMPTY;
                        map.put("comments", comments);
                        return map;
                    });
        }

        private boolean itemIsExistedInWarehouse(Long itemRrn, Long warehouseRrn) {

            String sql = "SELECT warehouse_id FROM " + DataBaseNames.WAREHOUSE_INVENTORY + " WHERE  item_rrn = " + itemRrn +
                    " AND " + " warehouse_rrn = " + warehouseRrn;

            SqlRowSet rs = jdbcTemplate.queryForRowSet(sql);

            return rs.next();
        }

        private void updateWarehouseInventoryForQty(Long warehouseRrn, Long itemRrn, Double receiptQty, Double issueQty,
                                                    Double adjustQty) {
            String sql = "UPDATE " + DataBaseNames.WAREHOUSE_INVENTORY + " SET " + " RECEIPT_QTY = NVL(RECEIPT_QTY, 0) + " +
                    "?, " + " ISSUE_QTY = NVL(ISSUE_QTY, 0) + ?, " + " ADJUST_QTY = NVL(ADJUST_QTY, 0) + ? " + " WHERE " +
                    "ITEM_RRN = ? AND WAREHOUSE_RRN = ? ";
            jdbcTemplate.update(sql, receiptQty, issueQty, adjustQty, itemRrn, warehouseRrn);
        }

    }