org.generationcp.middleware.manager.InventoryDataManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.generationcp.middleware.manager.InventoryDataManagerImpl.java

Source

/*******************************************************************************
 * Copyright (c) 2012, All Rights Reserved.
 *
 * Generation Challenge Programme (GCP)
 *
 *
 * This software is licensed for use under the terms of the GNU General Public License (http://bit.ly/8Ztv8M) and the provisions of Part F
 * of the Generation Challenge Programme Amended Consortium Agreement (http://bit.ly/KQX1nL)
 *
 *******************************************************************************/

package org.generationcp.middleware.manager;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import org.generationcp.middleware.dao.ims.LotDAO;
import org.generationcp.middleware.dao.ims.StockTransactionDAO;
import org.generationcp.middleware.dao.ims.TransactionDAO;
import org.generationcp.middleware.domain.gms.GermplasmListType;
import org.generationcp.middleware.domain.inventory.GermplasmInventory;
import org.generationcp.middleware.domain.inventory.InventoryDetails;
import org.generationcp.middleware.domain.inventory.ListEntryLotDetails;
import org.generationcp.middleware.domain.inventory.LotDetails;
import org.generationcp.middleware.domain.oms.Term;
import org.generationcp.middleware.exceptions.MiddlewareQueryException;
import org.generationcp.middleware.hibernate.HibernateSessionProvider;
import org.generationcp.middleware.manager.api.InventoryDataManager;
import org.generationcp.middleware.pojos.Germplasm;
import org.generationcp.middleware.pojos.GermplasmList;
import org.generationcp.middleware.pojos.GermplasmListData;
import org.generationcp.middleware.pojos.Location;
import org.generationcp.middleware.pojos.Person;
import org.generationcp.middleware.pojos.ims.Lot;
import org.generationcp.middleware.pojos.ims.ReservedInventoryKey;
import org.generationcp.middleware.pojos.ims.StockTransaction;
import org.generationcp.middleware.pojos.report.LotReportRow;
import org.generationcp.middleware.pojos.report.TransactionReportRow;
import org.generationcp.middleware.service.api.user.UserService;
import org.generationcp.middleware.util.Util;
import org.hibernate.HibernateException;
import org.hibernate.SQLQuery;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Nullable;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Implementation of the InventoryDataManager interface. Most of the functions in this class only use the connection to the local instance,
 * this is because the lot and transaction tables only exist in a local instance.
 *
 * @author Kevin Manansala
 *
 */
@Transactional
public class InventoryDataManagerImpl extends DataManager implements InventoryDataManager {

    @Resource
    private UserService userService;

    private DaoFactory daoFactory;

    public InventoryDataManagerImpl() {
    }

    public InventoryDataManagerImpl(final HibernateSessionProvider sessionProvider) {
        super(sessionProvider);
        this.daoFactory = new DaoFactory(sessionProvider);
    }

    public InventoryDataManagerImpl(final HibernateSessionProvider sessionProvider, final String databaseName) {
        super(sessionProvider, databaseName);
        this.daoFactory = new DaoFactory(sessionProvider);
    }

    @Override
    public List<Lot> getLotsByEntityType(final String type, final int start, final int numOfRows) {
        return this.daoFactory.getLotDao().getByEntityType(type, start, numOfRows);
    }

    @Override
    public long countLotsByEntityType(final String type) {
        return this.daoFactory.getLotDao().countByEntityType(type);
    }

    @Override
    public List<Lot> getLotsByEntityTypeAndEntityId(final String type, final Integer entityId, final int start,
            final int numOfRows) {
        return this.daoFactory.getLotDao().getByEntityTypeAndEntityId(type, entityId, start, numOfRows);
    }

    @Override
    public long countLotsByEntityTypeAndEntityId(final String type, final Integer entityId) {
        return this.daoFactory.getLotDao().countByEntityTypeAndEntityId(type, entityId);
    }

    @Override
    public List<Lot> getLotsByEntityTypeAndLocationId(final String type, final Integer locationId, final int start,
            final int numOfRows) {
        return this.daoFactory.getLotDao().getByEntityTypeAndLocationId(type, locationId, start, numOfRows);
    }

    @Override
    public long countLotsByEntityTypeAndLocationId(final String type, final Integer locationId) {
        return this.daoFactory.getLotDao().countByEntityTypeAndLocationId(type, locationId);
    }

    @Override
    public List<Lot> getLotsByEntityTypeAndEntityIdAndLocationId(final String type, final Integer entityId,
            final Integer locationId, final int start, final int numOfRows) {
        return this.daoFactory.getLotDao().getByEntityTypeAndEntityIdAndLocationId(type, entityId, locationId,
                start, numOfRows);
    }

    @Override
    public long countLotsByEntityTypeAndEntityIdAndLocationId(final String type, final Integer entityId,
            final Integer locationId) {
        return this.daoFactory.getLotDao().countByEntityTypeAndEntityIdAndLocationId(type, entityId, locationId);
    }

    @Override
    public Double getActualLotBalance(final Integer lotId) {
        return this.daoFactory.getLotDao().getActualLotBalance(lotId);
    }

    @Override
    public Double getAvailableLotBalance(final Integer lotId) {
        return this.daoFactory.getLotDao().getAvailableLotBalance(lotId);
    }

    @Override
    public Integer addLot(final Lot lot) {
        final List<Lot> lots = new ArrayList<>();
        lots.add(lot);
        final List<Integer> ids = this.addOrUpdateLot(lots, Operation.ADD);
        return !ids.isEmpty() ? ids.get(0) : null;
    }

    @Override
    public List<Integer> addLots(final List<Lot> lots) {
        return this.addOrUpdateLot(lots, Operation.ADD);
    }

    @Override
    public Integer updateLot(final Lot lot) {
        final List<Lot> lots = new ArrayList<>();
        lots.add(lot);
        final List<Integer> ids = this.addOrUpdateLot(lots, Operation.UPDATE);
        return !ids.isEmpty() ? ids.get(0) : null;
    }

    @Override
    public List<Integer> updateLots(final List<Lot> lots) {
        return this.addOrUpdateLot(lots, Operation.UPDATE);
    }

    @Override
    public Integer addStockTransaction(StockTransaction stockTransaction) {
        try {
            final StockTransactionDAO stockTransactionDAO = this.daoFactory.getStockTransactionDAO();
            stockTransaction = stockTransactionDAO.saveOrUpdate(stockTransaction);
            return stockTransaction.getId();
        } catch (final HibernateException e) {
            throw new MiddlewareQueryException(e.getMessage(), e);
        }
    }

    private List<Integer> addOrUpdateLot(final List<Lot> lots, final Operation operation) {
        final List<Integer> idLotsSaved = new ArrayList<>();
        try {
            final LotDAO dao = this.daoFactory.getLotDao();
            for (final Lot lot : lots) {
                final Lot recordSaved = dao.saveOrUpdate(lot);
                idLotsSaved.add(recordSaved.getId());
            }
        } catch (final ConstraintViolationException e) {

            throw new MiddlewareQueryException(e.getMessage(), e);
        } catch (final MiddlewareQueryException e) {

            throw e;
        } catch (final Exception e) {

            throw new MiddlewareQueryException(
                    "Error encountered while saving Lot: InventoryDataManager.addOrUpdateLot(lots=" + lots
                            + ", operation=" + operation + "): " + e.getMessage(),
                    e);
        }

        return idLotsSaved;
    }

    @Override
    public Integer addTransaction(final org.generationcp.middleware.pojos.ims.Transaction transaction) {
        final List<org.generationcp.middleware.pojos.ims.Transaction> transactions = new ArrayList<>();
        transactions.add(transaction);
        final List<Integer> ids = this.addTransactions(transactions);
        return !ids.isEmpty() ? ids.get(0) : null;
    }

    @Override
    public List<Integer> addTransactions(
            final List<org.generationcp.middleware.pojos.ims.Transaction> transactions) {
        return this.addOrUpdateTransaction(transactions, Operation.ADD);
    }

    @Override
    public Integer updateTransaction(final org.generationcp.middleware.pojos.ims.Transaction transaction) {
        final List<org.generationcp.middleware.pojos.ims.Transaction> transactions = new ArrayList<>();
        transactions.add(transaction);
        final List<Integer> ids = this.addOrUpdateTransaction(transactions, Operation.UPDATE);
        return !ids.isEmpty() ? ids.get(0) : null;
    }

    @Override
    public List<Integer> updateTransactions(
            final List<org.generationcp.middleware.pojos.ims.Transaction> transactions) {
        return this.addOrUpdateTransaction(transactions, Operation.UPDATE);
    }

    private List<Integer> addOrUpdateTransaction(
            final List<org.generationcp.middleware.pojos.ims.Transaction> transactions, final Operation operation) {
        final List<Integer> idTransactionsSaved = new ArrayList<>();
        try {

            final TransactionDAO dao = this.daoFactory.getTransactionDAO();

            for (final org.generationcp.middleware.pojos.ims.Transaction transaction : transactions) {
                final org.generationcp.middleware.pojos.ims.Transaction recordSaved = dao.saveOrUpdate(transaction);
                idTransactionsSaved.add(recordSaved.getId());
            }

        } catch (final Exception e) {

            throw new MiddlewareQueryException(
                    "Error encountered while saving Transaction: InventoryDataManager.addOrUpdateTransaction(transactions="
                            + transactions + ", operation=" + operation + "): " + e.getMessage(),
                    e);
        }

        return idTransactionsSaved;
    }

    @Override
    public org.generationcp.middleware.pojos.ims.Transaction getTransactionById(final Integer id) {
        return this.daoFactory.getTransactionDAO().getById(id, false);
    }

    @Override
    public List<org.generationcp.middleware.pojos.ims.Transaction> getTransactionsByIdList(
            final List<Integer> idList) {
        return this.daoFactory.getTransactionDAO().filterByColumnValues("id", idList);
    }

    @Override
    public List<org.generationcp.middleware.pojos.ims.Lot> getLotsByIdList(final List<Integer> idList) {
        return this.daoFactory.getLotDao().filterByColumnValues("id", idList);
    }

    @Override
    public Set<org.generationcp.middleware.pojos.ims.Transaction> getTransactionsByLotId(final Integer id) {
        final Lot lot = this.daoFactory.getLotDao().getById(id, false);
        return lot.getTransactions();
    }

    @Override
    public List<org.generationcp.middleware.pojos.ims.Transaction> getAllTransactions(final int start,
            final int numOfRows) {
        return this.daoFactory.getTransactionDAO().getAll(start, numOfRows);
    }

    @Override
    public List<org.generationcp.middleware.pojos.ims.Transaction> getAllReserveTransactions(final int start,
            final int numOfRows) {
        return this.daoFactory.getTransactionDAO().getAllReserve(start, numOfRows);
    }

    @Override
    public long countAllReserveTransactions() {
        return this.daoFactory.getTransactionDAO().countAllReserve();
    }

    @Override
    public List<org.generationcp.middleware.pojos.ims.Transaction> getAllDepositTransactions(final int start,
            final int numOfRows) {
        return this.daoFactory.getTransactionDAO().getAllDeposit(start, numOfRows);
    }

    @Override
    public long countAllDepositTransactions() {
        return this.daoFactory.getTransactionDAO().countAllDeposit();
    }

    @Override
    public List<TransactionReportRow> generateReportOnAllUncommittedTransactions(final int start,
            final int numOfRows) {
        final List<TransactionReportRow> report = new ArrayList<>();

        final LocationDataManagerImpl locationManager = new LocationDataManagerImpl(this.getSessionProvider());
        final OntologyDataManagerImpl ontologyManager = new OntologyDataManagerImpl(this.getSessionProvider());

        final List<org.generationcp.middleware.pojos.ims.Transaction> transactions = this.daoFactory
                .getTransactionDAO().getAllUncommitted(start, numOfRows);

        for (final org.generationcp.middleware.pojos.ims.Transaction t : transactions) {
            final TransactionReportRow row = new TransactionReportRow();
            row.setDate(t.getTransactionDate());
            row.setQuantity(t.getQuantity());
            row.setCommentOfLot(t.getLot().getComments());
            row.setLotDate(t.getLot().getCreatedDate());

            final Term termScale = ontologyManager.getTermById(t.getLot().getScaleId());
            row.setScaleOfLot(termScale);

            final Location location = locationManager.getLocationByID(t.getLot().getLocationId());
            row.setLocationOfLot(location);

            report.add(row);
        }
        return report;
    }

    @Override
    public long countAllUncommittedTransactions() {
        return this.daoFactory.getTransactionDAO().countAllUncommitted();
    }

    @Override
    public List<TransactionReportRow> generateReportOnAllReserveTransactions(final int start, final int numOfRows) {

        final List<TransactionReportRow> report = new ArrayList<>();
        final LocationDataManagerImpl locationManager = new LocationDataManagerImpl(this.getSessionProvider());
        final OntologyDataManagerImpl ontologyManager = new OntologyDataManagerImpl(this.getSessionProvider());

        final List<org.generationcp.middleware.pojos.ims.Transaction> transactions = this
                .getAllReserveTransactions(start, numOfRows);
        for (final org.generationcp.middleware.pojos.ims.Transaction t : transactions) {
            final TransactionReportRow row = new TransactionReportRow();
            row.setDate(t.getTransactionDate());
            row.setQuantity(t.getQuantity());
            row.setCommentOfLot(t.getLot().getComments());
            row.setEntityIdOfLot(t.getLot().getEntityId());
            row.setLotDate(t.getLot().getCreatedDate());

            final Term termScale = ontologyManager.getTermById(t.getLot().getScaleId());
            row.setScaleOfLot(termScale);

            final Location location = locationManager.getLocationByID(t.getLot().getLocationId());
            row.setLocationOfLot(location);

            report.add(row);
        }

        return report;
    }

    @Override
    public long countAllWithdrawalTransactions() {
        return this.daoFactory.getTransactionDAO().countAllWithdrawals();
    }

    @Override
    public List<TransactionReportRow> generateReportOnAllWithdrawalTransactions(final int start,
            final int numOfRows) {
        final List<TransactionReportRow> report = new ArrayList<>();

        final LocationDataManagerImpl locationManager = new LocationDataManagerImpl(this.getSessionProvider());
        final OntologyDataManagerImpl ontologyManager = new OntologyDataManagerImpl(this.getSessionProvider());

        final List<org.generationcp.middleware.pojos.ims.Transaction> transactions = this.daoFactory
                .getTransactionDAO().getAllWithdrawals(start, numOfRows);
        for (final org.generationcp.middleware.pojos.ims.Transaction t : transactions) {
            final TransactionReportRow row = new TransactionReportRow();
            row.setDate(t.getTransactionDate());
            row.setQuantity(t.getQuantity());
            row.setCommentOfLot(t.getLot().getComments());
            row.setEntityIdOfLot(t.getLot().getEntityId());
            row.setLotDate(t.getLot().getCreatedDate());

            final Term termScale = ontologyManager.getTermById(t.getLot().getScaleId());
            row.setScaleOfLot(termScale);

            final Location location = locationManager.getLocationByID(t.getLot().getLocationId());
            row.setLocationOfLot(location);

            final Person person = this.userService.getPersonById(t.getPersonId());
            row.setPerson(person);

            report.add(row);
        }
        return report;
    }

    @Override
    public List<Lot> getAllLots(final int start, final int numOfRows) {
        return this.daoFactory.getLotDao().getAll(start, numOfRows);
    }

    @Override
    public long countAllLots() {
        return this.daoFactory.getLotDao().countAll();
    }

    @Override
    public List<LotReportRow> generateReportOnAllLots(final int start, final int numOfRows) {
        final List<Lot> allLots = this.getAllLots(start, numOfRows);
        return this.generateLotReportRows(allLots);
    }

    @Override
    public List<LotReportRow> generateReportOnDormantLots(final int year, final int start, final int numOfRows) {

        final SQLQuery query = this.getActiveSession().createSQLQuery(Lot.GENERATE_REPORT_ON_DORMANT);
        query.setParameter("year", year);
        query.setFirstResult(start);
        query.setMaxResults(numOfRows);

        final LocationDataManagerImpl locationManager = new LocationDataManagerImpl(this.getSessionProvider());
        final OntologyDataManagerImpl ontologyManager = new OntologyDataManagerImpl(this.getSessionProvider());
        final List<LotReportRow> report = new ArrayList<>();

        final List<?> results = query.list();
        for (final Object o : results) {
            final Object[] result = (Object[]) o;
            if (result != null) {
                final LotReportRow row = new LotReportRow();

                row.setLotId((Integer) result[0]);

                row.setEntityIdOfLot((Integer) result[1]);

                row.setActualLotBalance(((Double) result[2]).doubleValue());

                final Location location = locationManager.getLocationByID((Integer) result[3]);
                row.setLocationOfLot(location);

                final Term termScale = ontologyManager.getTermById((Integer) result[4]);
                row.setScaleOfLot(termScale);

                report.add(row);
            }
        }
        return report;
    }

    @Override
    public List<LotReportRow> generateReportOnEmptyLots(final int start, final int numOfRows) {
        final List<Lot> emptyLots = new ArrayList<>();
        for (final org.generationcp.middleware.pojos.ims.Transaction t : this.daoFactory.getTransactionDAO()
                .getEmptyLot(start, numOfRows)) {
            emptyLots.add(t.getLot());
        }
        return this.generateLotReportRows(emptyLots);
    }

    @Override
    public List<LotReportRow> generateReportOnLotsWithMinimumAmount(final long minAmount, final int start,
            final int numOfRows) {
        final List<Lot> lotsWithMinimunAmount = new ArrayList<>();
        for (final org.generationcp.middleware.pojos.ims.Transaction t : this.daoFactory.getTransactionDAO()
                .getLotWithMinimumAmount(minAmount, start, numOfRows)) {
            lotsWithMinimunAmount.add(t.getLot());
        }
        return this.generateLotReportRows(lotsWithMinimunAmount);
    }

    @Override
    public List<LotReportRow> generateReportOnLotsByEntityType(final String type, final int start,
            final int numOfRows) {
        final List<Lot> lotsByEntity = this.getLotsByEntityType(type, start, numOfRows);
        return this.generateLotReportRows(lotsByEntity);
    }

    @Override
    public List<LotReportRow> generateReportOnLotsByEntityTypeAndEntityId(final String type, final Integer entityId,
            final int start, final int numOfRows) {
        final List<Integer> entityIds = new ArrayList<>();
        entityIds.add(entityId);
        return this.generateReportOnLotsByEntityTypeAndEntityId(type, entityIds, start, numOfRows);
    }

    @Override
    public List<LotReportRow> generateReportOnLotsByEntityTypeAndEntityId(final String type,
            final List<Integer> entityIds, final int start, final int numOfRows) {
        final List<Lot> lotsByEntityTypeAndEntityId = new ArrayList<>();
        for (final Integer entityId : entityIds) {
            final List<Lot> lotsForEntityId = this.getLotsByEntityTypeAndEntityId(type, entityId, start, numOfRows);
            lotsByEntityTypeAndEntityId.addAll(lotsForEntityId);
        }
        return this.generateLotReportRows(lotsByEntityTypeAndEntityId);
    }

    private List<LotReportRow> generateLotReportRows(final List<Lot> listOfLots) {

        final LocationDataManagerImpl locationManager = new LocationDataManagerImpl(this.getSessionProvider());
        final OntologyDataManagerImpl ontologyManager = new OntologyDataManagerImpl(this.getSessionProvider());
        final List<LotReportRow> report = new ArrayList<>();
        for (final Lot lot : listOfLots) {
            final LotReportRow row = new LotReportRow();

            row.setLotId(lot.getId());

            row.setEntityIdOfLot(lot.getEntityId());

            final Double lotBalance = this.getActualLotBalance(lot.getId());
            row.setActualLotBalance(lotBalance);

            final Location location = locationManager.getLocationByID(lot.getLocationId());
            row.setLocationOfLot(location);

            final Term termScale = ontologyManager.getTermById(lot.getScaleId());
            row.setScaleOfLot(termScale);

            row.setCommentOfLot(lot.getComments());

            report.add(row);
        }
        return report;
    }

    private List<GermplasmListData> getGermplasmListDataByListId(final Integer id) {
        return this.daoFactory.getGermplasmListDataDAO().getByListId(id);
    }

    @Override
    public boolean transactionsExistForListProjectDataListID(final Integer listDataProjectListID) {
        return this.daoFactory.getStockTransactionDAO()
                .listDataProjectListHasStockTransactions(listDataProjectListID);
    }

    @Override
    public List<ListEntryLotDetails> getLotDetailsForListEntry(final Integer listId, final Integer recordId,
            final Integer gid) {
        return this.getListInventoryBuilder().retrieveInventoryLotsForListEntry(listId, recordId, gid);
    }

    @Override
    public List<GermplasmListData> getLotDetailsForList(final Integer listId, final int start,
            final int numOfRows) {
        final List<GermplasmListData> listEntries = this.getGermplasmListDataByListId(listId);
        return this.getListInventoryBuilder().retrieveInventoryLotsForList(listId, start, numOfRows, listEntries);
    }

    @Override
    public List<GermplasmListData> getReservedLotDetailsForExportList(final Integer listId) {
        final List<GermplasmListData> listEntries = this.getGermplasmListDataByListId(listId);
        return this.getListInventoryBuilder().retrieveReservedInventoryLotsForList(listId, listEntries);
    }

    @Override
    public List<GermplasmListData> getLotCountsForList(final Integer id, final int start, final int numOfRows) {
        final List<GermplasmListData> listEntries = this.getGermplasmListDataByListId(id);
        return this.getListInventoryBuilder().retrieveLotCountsForList(listEntries);
    }

    @Override
    public void populateLotCountsIntoExistingList(final GermplasmList germplasmList) {
        this.getListInventoryBuilder().retrieveLotCountsForList(germplasmList.getListData());
    }

    @Override
    public Integer countLotsWithAvailableBalanceForGermplasm(final Integer gid) {
        return this.getListInventoryBuilder().countLotsWithAvailableBalanceForGermplasm(gid);
    }

    @Override
    public List<LotDetails> getLotDetailsForGermplasm(final Integer gid) {
        return this.getListInventoryBuilder().retrieveInventoryLotsForGermplasm(gid);
    }

    @Override
    public List<GermplasmListData> getLotCountsForListEntries(final Integer listId, final List<Integer> entryIds) {
        return this.getListInventoryBuilder().retrieveLotCountsForListEntries(listId, entryIds);
    }

    @Override
    public void cancelReservedInventory(final List<ReservedInventoryKey> lotEntries) {
        for (final ReservedInventoryKey entry : lotEntries) {
            final Integer lotId = entry.getLotId();
            final Integer lrecId = entry.getLrecId();

            this.daoFactory.getTransactionDAO().cancelReservationsForLotEntryAndLrecId(lotId, lrecId);
        }
    }

    @Override
    public boolean isStockIdExists(final List<String> stockIDs) {
        return this.daoFactory.getTransactionDAO().isStockIdExists(stockIDs);
    }

    @Override
    public List<String> getSimilarStockIds(final List<String> stockIDs) {
        return this.daoFactory.getTransactionDAO().getSimilarStockIds(stockIDs);
    }

    @Override
    public List<String> getStockIdsByListDataProjectListId(final Integer listId) {
        return this.daoFactory.getTransactionDAO().getStockIdsByListDataProjectListId(listId);
    }

    @Override
    public void updateInventory(final Integer listId, final List<InventoryDetails> inventoryDetailList) {

        try {

            final GermplasmList germplasmList = this.daoFactory.getGermplasmListDAO().getById(listId);
            final GermplasmListType germplasmListType = GermplasmListType.valueOf(germplasmList.getType());
            for (final InventoryDetails inventoryDetails : inventoryDetailList) {
                final Lot lot = this.daoFactory.getLotDao().getById(inventoryDetails.getLotId());
                lot.setLocationId(inventoryDetails.getLocationId());
                lot.setScaleId(inventoryDetails.getScaleId());
                this.daoFactory.getLotDao().saveOrUpdate(lot);
                final org.generationcp.middleware.pojos.ims.Transaction transaction = this
                        .getTransactionById(inventoryDetails.getTrnId());
                transaction.setQuantity(Util.zeroIfNull(inventoryDetails.getAmount()));
                transaction.setComments(Util.nullIfEmpty(inventoryDetails.getComment()));
                if (GermplasmListType.isCrosses(germplasmListType)) {
                    transaction.setBulkWith(Util.nullIfEmpty(inventoryDetails.getBulkWith()));
                    transaction.setBulkCompl(Util.nullIfEmpty(inventoryDetails.getBulkCompl()));
                }
                this.daoFactory.getTransactionDAO().saveOrUpdate(transaction);
            }

        } catch (final Exception e) {

            this.logAndThrowException(
                    "Error encountered while updating inventory " + "of list id " + listId + "." + e.getMessage(),
                    e);
        }
    }

    @Override
    public Lot getLotById(final Integer id) {
        return this.daoFactory.getLotDao().getById(id, false);
    }

    @Override
    public List<TransactionReportRow> getTransactionDetailsForLot(final Integer lotId) {
        final List<TransactionReportRow> transactionDetailsForLot = this.daoFactory.getTransactionDAO()
                .getTransactionDetailsForLot(lotId);
        final List<Integer> userIds = Lists.transform(transactionDetailsForLot,
                new Function<TransactionReportRow, Integer>() {

                    @Nullable
                    @Override
                    public Integer apply(@Nullable final TransactionReportRow input) {
                        return input.getUserId();
                    }
                });
        if (!userIds.isEmpty()) {
            final Map<Integer, String> userIDFullNameMap = this.userService.getUserIDFullNameMap(userIds);
            for (final TransactionReportRow row : transactionDetailsForLot) {
                if (row.getUserId() != null) {
                    row.setUser(userIDFullNameMap.get(row.getUserId()));
                }
            }
        }
        return transactionDetailsForLot;
    }

    @Override
    public List<Germplasm> getAvailableBalanceForGermplasms(final List<Germplasm> germplasms) {
        final List<Integer> gids = new ArrayList<>();

        for (final Germplasm germplasm : germplasms) {
            gids.add(germplasm.getGid());
            germplasm.setInventoryInfo(new GermplasmInventory(germplasm.getGid()));
        }

        final Map<Integer, Object[]> availableBalanceCountAndTotalLotsCount = this.daoFactory.getLotDao()
                .getAvailableBalanceCountAndTotalLotsCount(gids);

        for (final Germplasm germplasm : germplasms) {
            final Object[] availableBalanceValues = availableBalanceCountAndTotalLotsCount.get(germplasm.getGid());
            this.getListInventoryBuilder().setAvailableBalanceAndScale(germplasm.getInventoryInfo(),
                    availableBalanceValues);
        }

        this.getListInventoryBuilder().setAvailableBalanceScaleForGermplasm(germplasms);
        return germplasms;
    }

    @Override
    public Map<Integer, String> retrieveStockIds(final List<Integer> gids) {
        return this.daoFactory.getTransactionDAO().retrieveStockIds(gids);
    }

}