package org.openlmis.core.presenter;
import android.support.annotation.NonNull;
import com.google.inject.Inject;
import org.openlmis.core.exceptions.LMISException;
import org.openlmis.core.exceptions.ViewNotMatchException;
import org.openlmis.core.manager.MovementReasonManager;
import org.openlmis.core.model.KitProduct;
import org.openlmis.core.model.LotOnHand;
import org.openlmis.core.model.Product;
import org.openlmis.core.model.StockCard;
import org.openlmis.core.model.StockMovementItem;
import org.openlmis.core.model.repository.ProductRepository;
import org.openlmis.core.model.repository.StockRepository;
import org.openlmis.core.utils.DateUtil;
import org.openlmis.core.view.BaseView;
import org.openlmis.core.view.viewmodel.InventoryViewModel;
import org.openlmis.core.view.viewmodel.LotMovementViewModel;
import org.openlmis.core.view.viewmodel.UnpackKitInventoryViewModel;
import org.roboguice.shaded.goole.common.base.Function;
import org.roboguice.shaded.goole.common.base.Predicate;
import org.roboguice.shaded.goole.common.collect.FluentIterable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import lombok.Getter;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
public class UnpackKitPresenter extends Presenter {
@Inject
private ProductRepository productRepository;
@Inject
private StockRepository stockRepository;
protected String kitCode;
@Getter
protected final List<InventoryViewModel> inventoryViewModels = new ArrayList<>();
@Override
public void attachView(BaseView v) throws ViewNotMatchException {
}
public UnpackKitPresenter() {
}
public Observable<List<InventoryViewModel>> getKitProductsObservable(final String kitCode, final int kitNum) {
return Observable.create(new Observable.OnSubscribe<List<InventoryViewModel>>() {
@Override
public void call(Subscriber<? super List<InventoryViewModel>> subscriber) {
try {
UnpackKitPresenter.this.kitCode = kitCode;
inventoryViewModels.clear();
List<KitProduct> kitProducts = productRepository.queryKitProductByKitCode(kitCode);
for (KitProduct kitProduct : kitProducts) {
final Product product = productRepository.getByCode(kitProduct.getProductCode());
InventoryViewModel inventoryViewModel = new UnpackKitInventoryViewModel(product);
setExistingLotViewModels(inventoryViewModel);
inventoryViewModel.setKitExpectQuantity(kitProduct.getQuantity() * kitNum);
inventoryViewModel.setChecked(true);
inventoryViewModels.add(inventoryViewModel);
}
subscriber.onNext(inventoryViewModels);
subscriber.onCompleted();
} catch (LMISException e) {
subscriber.onError(e);
}
}
}).observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io());
}
public Observable saveUnpackProductsObservable(final int kitUnpackQuantity, final String documentNumber, final String signature) {
return Observable.create(new Observable.OnSubscribe<Void>() {
@Override
public void call(final Subscriber<? super Void> subscriber) {
try {
List<StockCard> stockCards = new ArrayList<>();
stockCards.addAll(FluentIterable.from(inventoryViewModels).filter(new Predicate<InventoryViewModel>() {
@Override
public boolean apply(InventoryViewModel inventoryViewModel) {
return inventoryViewModel.getLotListQuantityTotalAmount() > 0;
}
}).transform(new Function<InventoryViewModel, StockCard>() {
@Override
public StockCard apply(InventoryViewModel inventoryViewModel) {
try {
return createStockCardForProductWithLot(inventoryViewModel, documentNumber, signature);
} catch (LMISException e) {
subscriber.onError(e);
}
return null;
}
}).toList());
stockCards.add(getStockCardForKit(kitUnpackQuantity, documentNumber, signature));
stockRepository.batchSaveUnpackStockCardsWithMovementItemsAndUpdateProduct(stockCards);
subscriber.onNext(null);
subscriber.onCompleted();
} catch (LMISException exception) {
subscriber.onError(exception);
}
}
}).observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io());
}
protected StockCard getStockCardForKit(int kitUnpackQuantity, String documentNumber, String signature) throws LMISException {
Product kit = productRepository.getByCode(kitCode);
StockCard kitStockCard = stockRepository.queryStockCardByProductId(kit.getId());
kitStockCard.setStockOnHand(kitStockCard.getStockOnHand() - kitUnpackQuantity);
if (0 == kitStockCard.getStockOnHand()) {
kitStockCard.setExpireDates("");
}
StockMovementItem kitMovementItem = new StockMovementItem(kitStockCard);
kitMovementItem.setReason(MovementReasonManager.UNPACK_KIT);
kitMovementItem.setMovementType(MovementReasonManager.MovementType.ISSUE);
kitMovementItem.setMovementQuantity(kitUnpackQuantity);
kitMovementItem.setSignature(signature);
kitMovementItem.setDocumentNumber(documentNumber);
List<StockMovementItem> stockMovementItems = new ArrayList<>();
stockMovementItems.add(kitMovementItem);
kitStockCard.setStockMovementItemsWrapper(stockMovementItems);
return kitStockCard;
}
@NonNull
protected StockCard createStockCardForProductWithLot(InventoryViewModel inventoryViewModel, String documentNumber, String signature) throws LMISException {
List<StockMovementItem> stockMovementItems = new ArrayList<>();
StockCard stockCard = stockRepository.queryStockCardByProductId(inventoryViewModel.getProductId());
if (stockCard == null) {
stockCard = new StockCard();
stockCard.setProduct(inventoryViewModel.getProduct());
stockMovementItems.add(stockCard.generateInitialStockMovementItem());
}
stockCard.getProduct().setArchived(false);
List<LotMovementViewModel> totalLotMovementViewModelList = new ArrayList<>();
totalLotMovementViewModelList.addAll(FluentIterable.from(inventoryViewModel.getExistingLotMovementViewModelList()).filter(new Predicate<LotMovementViewModel>() {
@Override
public boolean apply(LotMovementViewModel lotMovementViewModel) {
return lotMovementViewModel.quantityGreaterThanZero();
}
}).toList());
totalLotMovementViewModelList.addAll(inventoryViewModel.getNewLotMovementViewModelList());
stockMovementItems.add(createUnpackMovementItemAndLotMovement(stockCard, documentNumber, signature, totalLotMovementViewModelList));
stockCard.setStockOnHand(stockMovementItems.get(stockMovementItems.size() - 1).getStockOnHand());
stockCard.setStockMovementItemsWrapper(stockMovementItems);
return stockCard;
}
@NonNull
private StockMovementItem createUnpackMovementItemAndLotMovement(StockCard stockCard, String documentNumber, String signature, List<LotMovementViewModel> lotMovementViewModelList) {
StockMovementItem unpackMovementItem = new StockMovementItem(stockCard);
unpackMovementItem.setReason(MovementReasonManager.DDM);
unpackMovementItem.setMovementType(MovementReasonManager.MovementType.RECEIVE);
unpackMovementItem.setDocumentNumber(documentNumber);
unpackMovementItem.setSignature(signature);
unpackMovementItem.populateLotQuantitiesAndCalculateNewSOH(lotMovementViewModelList, unpackMovementItem.getMovementType());
return unpackMovementItem;
}
private void setExistingLotViewModels(InventoryViewModel inventoryViewModel) throws LMISException {
StockCard stockCard = stockRepository.queryStockCardByProductId(inventoryViewModel.getProductId());
if (stockCard != null) {
List<LotMovementViewModel> lotMovementViewModels = FluentIterable.from(stockCard.getNonEmptyLotOnHandList()).transform(new Function<LotOnHand, LotMovementViewModel>() {
@Override
public LotMovementViewModel apply(LotOnHand lotOnHand) {
return new LotMovementViewModel(lotOnHand.getLot().getLotNumber(),
DateUtil.formatDate(lotOnHand.getLot().getExpirationDate(), DateUtil.DATE_FORMAT_ONLY_MONTH_AND_YEAR),
lotOnHand.getQuantityOnHand().toString(), MovementReasonManager.MovementType.RECEIVE);
}
}).toSortedList(new Comparator<LotMovementViewModel>() {
@Override
public int compare(LotMovementViewModel lot1, LotMovementViewModel lot2) {
return DateUtil.parseString(lot1.getExpiryDate(), DateUtil.DATE_FORMAT_ONLY_MONTH_AND_YEAR).compareTo(DateUtil.parseString(lot2.getExpiryDate(), DateUtil.DATE_FORMAT_ONLY_MONTH_AND_YEAR));
}
});
inventoryViewModel.setExistingLotMovementViewModelList(lotMovementViewModels);
}
}
}