/*
* 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.presenter;
import com.google.inject.Inject;
import org.openlmis.core.exceptions.LMISException;
import org.openlmis.core.model.Product;
import org.openlmis.core.model.Product.IsKit;
import org.openlmis.core.model.StockCard;
import org.openlmis.core.model.repository.ProductRepository;
import org.openlmis.core.model.repository.StockRepository;
import org.openlmis.core.model.service.RequisitionPeriodService;
import org.openlmis.core.model.service.StockService;
import org.openlmis.core.utils.ToastUtil;
import org.openlmis.core.view.BaseView;
import org.openlmis.core.view.viewmodel.InventoryViewModel;
import org.roboguice.shaded.goole.common.base.Function;
import org.roboguice.shaded.goole.common.base.Predicate;
import java.util.ArrayList;
import java.util.List;
import rx.Observable;
import rx.Observer;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import static org.roboguice.shaded.goole.common.collect.FluentIterable.from;
public class StockCardPresenter extends Presenter {
private List<InventoryViewModel> inventoryViewModels;
@Inject
StockRepository stockRepository;
@Inject
ProductRepository productRepository;
@Inject
StockService stockService;
@Inject
RequisitionPeriodService requisitionPeriodService;
Observer<List<StockCard>> afterLoadHandler = getLoadStockCardsSubscriber();
private StockCardListView view;
public StockCardPresenter() {
inventoryViewModels = new ArrayList<>();
}
public List<InventoryViewModel> getInventoryViewModels() {
return inventoryViewModels;
}
public void loadStockCards(ArchiveStatus status) {
view.loading();
Subscription subscription = getLoadStockCardsObservable(status).subscribe(afterLoadHandler);
subscriptions.add(subscription);
}
public void loadKits() {
view.loading();
Subscription subscription = createOrGetKitStockCardsObservable().subscribe(afterLoadHandler);
subscriptions.add(subscription);
}
public void refreshStockCardViewModelsSOH() {
for (InventoryViewModel inventoryViewModel : inventoryViewModels) {
final StockCard stockCard = inventoryViewModel.getStockCard();
stockRepository.refresh(stockCard);
inventoryViewModel.setStockOnHand(stockCard.getStockOnHand());
}
}
@Override
public void attachView(BaseView v) {
view = (StockCardListView) v;
}
public void archiveBackStockCard(StockCard stockCard) {
stockCard.getProduct().setArchived(false);
stockCard.setExpireDates("");
try {
stockRepository.updateStockCardWithProduct(stockCard);
} catch (LMISException e) {
e.reportToFabric();
}
}
private Observable<List<StockCard>> getLoadStockCardsObservable(final ArchiveStatus status) {
return Observable.create(new Observable.OnSubscribe<List<StockCard>>() {
@Override
public void call(Subscriber<? super List<StockCard>> subscriber) {
stockService.monthlyUpdateAvgMonthlyConsumption();
subscriber.onNext(from(stockRepository.list()).filter(new Predicate<StockCard>() {
@Override
public boolean apply(StockCard stockCard) {
if (status.isArchived()) {
return showInArchiveView(stockCard);
}
return showInOverview(stockCard);
}
}).toList());
subscriber.onCompleted();
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
private boolean showInOverview(StockCard stockCard) {
return !stockCard.getProduct().isKit() && (stockCard.getStockOnHand() > 0 || (stockCard.getProduct().isActive() && !stockCard.getProduct().isArchived()));
}
private boolean showInArchiveView(StockCard stockCard) {
return stockCard.getStockOnHand() == 0 && (stockCard.getProduct().isArchived() || !stockCard.getProduct().isActive());
}
private Observer<List<StockCard>> getLoadStockCardsSubscriber() {
return new Observer<List<StockCard>>() {
@Override
public void onCompleted() {
view.loaded();
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
ToastUtil.show(e.getMessage());
view.loaded();
}
@Override
public void onNext(List<StockCard> stockCards) {
List<InventoryViewModel> inventoryViewModelList = from(stockCards).transform(new Function<StockCard, InventoryViewModel>() {
@Override
public InventoryViewModel apply(StockCard stockCard) {
return new InventoryViewModel(stockCard);
}
}).toList();
inventoryViewModels.clear();
inventoryViewModels.addAll(inventoryViewModelList);
view.refresh(inventoryViewModels);
}
};
}
private Observable<List<StockCard>> createOrGetKitStockCardsObservable() {
return Observable.create(new Observable.OnSubscribe<List<StockCard>>() {
@Override
public void call(Subscriber<? super List<StockCard>> subscriber) {
try {
final List<Product> kits = productRepository.listActiveProducts(IsKit.Yes);
subscriber.onNext(createStockCardsIfNotExist(kits));
subscriber.onCompleted();
} catch (LMISException e) {
subscriber.onError(e);
}
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
private List<StockCard> createStockCardsIfNotExist(List<Product> kits) {
return from(kits).transform(new Function<Product, StockCard>() {
@Override
public StockCard apply(Product product) {
StockCard stockCard = null;
try {
stockCard = stockRepository.queryStockCardByProductId(product.getId());
if (stockCard == null) {
stockCard = new StockCard();
stockCard.setProduct(product);
stockRepository.createOrUpdateStockCardWithStockMovement(stockCard);
}
} catch (LMISException e) {
e.reportToFabric();
}
return stockCard;
}
}).toList();
}
public enum ArchiveStatus {
Archived(true),
Active(false);
private boolean isArchived;
ArchiveStatus(boolean isArchived) {
this.isArchived = isArchived;
}
public boolean isArchived() {
return isArchived;
}
}
public interface StockCardListView extends BaseView {
void refresh(List<InventoryViewModel> data);
}
}