/* * This program is part of the OpenLMIS logistics management information * system platform software. * * Copyright © 2015 ThoughtWorks, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. This program is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. You should * have received a copy of the GNU Affero General Public License along with * this program. If not, see http://www.gnu.org/licenses. For additional * information contact info@OpenLMIS.org */ package org.openlmis.core.view.viewmodel; import org.apache.commons.lang3.StringUtils; import org.openlmis.core.exceptions.MovementReasonNotFoundException; import org.openlmis.core.manager.MovementReasonManager; import org.openlmis.core.model.StockCard; import org.openlmis.core.model.StockMovementItem; import org.openlmis.core.utils.DateUtil; import org.roboguice.shaded.goole.common.base.Predicate; import org.roboguice.shaded.goole.common.collect.FluentIterable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor public class StockMovementViewModel extends BaseStockMovementViewModel { MovementReasonManager.MovementReason reason; String movementDate; String documentNo; String signature; boolean isKit; String requested; //old String stockExistence; boolean isDraft = true; //new private HashMap<MovementReasonManager.MovementType, String> typeQuantityMap = new HashMap<>(); public StockMovementViewModel(StockMovementItem item) { product = item.getStockCard().getProduct(); movementDate = DateUtil.formatDate(item.getMovementDate()); documentNo = item.getDocumentNumber(); stockExistence = String.valueOf(item.getStockOnHand()); signature = item.getSignature(); if (null == item.getRequested()) { requested = ""; } else { requested = String.valueOf(item.getRequested()); } isDraft = false; try { reason = MovementReasonManager.getInstance().queryByCode(item.getReason()); } catch (MovementReasonNotFoundException e) { throw new RuntimeException("MovementReason Cannot be find " + e.getMessage()); } typeQuantityMap.put(item.getMovementType(), String.valueOf(item.getMovementQuantity())); } public String getReceived() { return typeQuantityMap.get(MovementReasonManager.MovementType.RECEIVE); } public void setReceived(String received) { typeQuantityMap.put(MovementReasonManager.MovementType.RECEIVE, received); } public String getIssued() { return typeQuantityMap.get(MovementReasonManager.MovementType.ISSUE); } public void setIssued(String issued) { typeQuantityMap.put(MovementReasonManager.MovementType.ISSUE, issued); } public String getNegativeAdjustment() { return typeQuantityMap.get(MovementReasonManager.MovementType.NEGATIVE_ADJUST); } public void setNegativeAdjustment(String negativeAdjustment) { typeQuantityMap.put(MovementReasonManager.MovementType.NEGATIVE_ADJUST, negativeAdjustment); } public String getPositiveAdjustment() { return typeQuantityMap.get(MovementReasonManager.MovementType.POSITIVE_ADJUST); } public void setPositiveAdjustment(String positiveAdjustment) { typeQuantityMap.put(MovementReasonManager.MovementType.POSITIVE_ADJUST, positiveAdjustment); } public StockMovementItem convertViewToModel(StockCard stockCard) { StockMovementItem stockMovementItem = new StockMovementItem(); stockMovementItem.setStockOnHand(Long.parseLong(getStockExistence())); stockMovementItem.setReason(reason.getCode()); stockMovementItem.setDocumentNumber(getDocumentNo()); stockMovementItem.setMovementType(reason.getMovementType()); if (isKit) { Long movementQuantity = Long.parseLong(typeQuantityMap.get(reason.getMovementType())); stockMovementItem.setMovementQuantity(movementQuantity); } stockMovementItem.setRequested((null == requested || requested.isEmpty()) ? null : Long.valueOf(requested)); stockMovementItem.setSignature(signature); stockMovementItem.setMovementDate(DateUtil.parseString(getMovementDate(), DateUtil.DEFAULT_DATE_FORMAT)); stockMovementItem.setStockCard(stockCard); List<LotMovementViewModel> totalLotMovementViewModelList = new ArrayList<>(); totalLotMovementViewModelList.addAll(FluentIterable.from(existingLotMovementViewModelList).filter(new Predicate<LotMovementViewModel>() { @Override public boolean apply(LotMovementViewModel lotMovementViewModel) { return lotMovementViewModel.quantityGreaterThanZero(); } }).toList()); totalLotMovementViewModelList.addAll(newLotMovementViewModelList); stockMovementItem.populateLotQuantitiesAndCalculateNewSOH(totalLotMovementViewModelList, stockMovementItem.getMovementType()); return stockMovementItem; } public boolean validateEmpty() { return reason != null && StringUtils.isNoneEmpty(movementDate) && !allQuantitiesEmpty(); } public boolean validateInputValid() { return (isAnyQuantitiesNumeric() && Long.parseLong(stockExistence) >= 0); } public boolean validateQuantitiesNotZero() { if (!StringUtils.isEmpty(getReceived())) { return Long.parseLong(getReceived()) > 0; } else if (!StringUtils.isEmpty(getIssued())) { return Long.parseLong(getIssued()) > 0; } else if (!StringUtils.isEmpty(getPositiveAdjustment())) { return Long.parseLong(getPositiveAdjustment()) > 0; } else if (!StringUtils.isEmpty(getNegativeAdjustment())) { return Long.parseLong(getNegativeAdjustment()) > 0; } return true; } public boolean isIssuedReason() { return getReason() != null && getReason().isIssueAdjustment(); } private boolean allQuantitiesEmpty() { return StringUtils.isEmpty(getReceived()) && StringUtils.isEmpty(getIssued()) && StringUtils.isEmpty(getPositiveAdjustment()) && StringUtils.isEmpty(getNegativeAdjustment()); } private boolean isAnyQuantitiesNumeric() { return StringUtils.isNumeric(getReceived()) || StringUtils.isNumeric(getNegativeAdjustment()) || StringUtils.isNumeric(getPositiveAdjustment()) || StringUtils.isNumeric(getIssued()); } public void populateStockExistence(long previousStockOnHand) { if (!isKit) { this.stockExistence = "" + previousStockOnHand; } else { MovementReasonManager.MovementType movementType = typeQuantityMap.keySet().iterator().next(); if (MovementReasonManager.MovementType.RECEIVE.equals(movementType) || MovementReasonManager.MovementType.POSITIVE_ADJUST.equals(movementType)) { this.stockExistence = "" + (previousStockOnHand + Long.parseLong(typeQuantityMap.get(movementType))); } else { this.stockExistence = "" + (previousStockOnHand - Long.parseLong(typeQuantityMap.get(movementType))); } } } public boolean movementQuantitiesExist() { for (LotMovementViewModel lot : existingLotMovementViewModelList) { if (lot.quantityGreaterThanZero()) return true; } return !newLotMovementViewModelList.isEmpty(); } public boolean isLotEmpty() { return newLotMovementViewModelList.isEmpty() && existingLotMovementViewModelList.isEmpty(); } public boolean validateSoonestToExpireLotsIssued() { boolean soonestToExpireLotsIssued = true; for (LotMovementViewModel lotMovementViewModel : existingLotMovementViewModelList) { if (!StringUtils.isEmpty(lotMovementViewModel.getQuantity()) && Long.parseLong(lotMovementViewModel.getQuantity()) > 0) { if (!soonestToExpireLotsIssued) { return false; } if (Long.parseLong(lotMovementViewModel.getQuantity()) < Long.parseLong(lotMovementViewModel.getLotSoh())) { soonestToExpireLotsIssued = false; } } else { soonestToExpireLotsIssued = false; } } return true; } public boolean hasLotDataChanged() { for (LotMovementViewModel lotMovementViewModel : existingLotMovementViewModelList) { if (lotMovementViewModel.isDataChanged) { return true; } } return !newLotMovementViewModelList.isEmpty(); } public boolean validateSignature() { return signature.length() >= 2 && signature.matches("\\D+"); } public boolean validateMovementReason() { return reason != null; } }