package org.openlmis.core.model.repository;
import android.content.Context;
import android.database.Cursor;
import com.google.inject.Inject;
import com.j256.ormlite.dao.Dao;
import org.openlmis.core.LMISApp;
import org.openlmis.core.exceptions.LMISException;
import org.openlmis.core.model.Lot;
import org.openlmis.core.model.LotMovementItem;
import org.openlmis.core.model.StockMovementItem;
import org.openlmis.core.persistence.DbUtil;
import org.openlmis.core.persistence.GenericDao;
import org.openlmis.core.persistence.LmisSqliteOpenHelper;
import org.openlmis.core.utils.DateUtil;
import org.roboguice.shaded.goole.common.collect.Lists;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class StockMovementRepository {
@Inject
DbUtil dbUtil;
@Inject
Context context;
@Inject
private LotRepository lotRepository;
GenericDao<StockMovementItem> genericDao;
@Inject
public StockMovementRepository(Context context) {
genericDao = new GenericDao<>(StockMovementItem.class, context);
}
public void create(StockMovementItem stockMovementItem) throws LMISException {
genericDao.create(stockMovementItem);
}
public List<StockMovementItem> listUnSynced() throws LMISException {
return dbUtil.withDao(StockMovementItem.class, new DbUtil.Operation<StockMovementItem, List<StockMovementItem>>() {
@Override
public List<StockMovementItem> operate(Dao<StockMovementItem, String> dao) throws SQLException {
return dao.queryBuilder().where().eq("synced", false).query();
}
});
}
protected void batchCreateOrUpdateStockMovementsAndLotInfo(final List<StockMovementItem> stockMovementItems) throws LMISException {
dbUtil.withDaoAsBatch(StockMovementItem.class, new DbUtil.Operation<StockMovementItem, Void>() {
@Override
public Void operate(Dao<StockMovementItem, String> dao) throws SQLException, LMISException {
for (StockMovementItem stockMovementItem : stockMovementItems) {
updateDateTimeIfEmpty(stockMovementItem);
dao.createOrUpdate(stockMovementItem);
lotRepository.batchCreateLotsAndLotMovements(stockMovementItem.getLotMovementItemListWrapper());
}
return null;
}
});
}
private void updateDateTimeIfEmpty(StockMovementItem stockMovementItem) {
if (stockMovementItem.getCreatedTime() == null) {
stockMovementItem.setCreatedTime(new Date());
}
stockMovementItem.setCreatedAt(new Date());
stockMovementItem.setUpdatedAt(new Date());
}
public void batchCreateStockMovementItemAndLotItems(final StockMovementItem stockMovementItem) throws LMISException {
stockMovementItem.setCreatedTime(new Date(LMISApp.getInstance().getCurrentTimeMillis()));
create(stockMovementItem);
lotRepository.batchCreateLotsAndLotMovements(stockMovementItem.getLotMovementItemListWrapper());
lotRepository.batchCreateLotsAndLotMovements(stockMovementItem.getNewAddedLotMovementItemListWrapper());
}
public void batchCreateOrUpdateStockMovementsAndLotMovements(final List<StockMovementItem> stockMovementItems) throws LMISException {
dbUtil.withDaoAsBatch(StockMovementItem.class, new DbUtil.Operation<StockMovementItem, Void>() {
@Override
public Void operate(Dao<StockMovementItem, String> dao) throws SQLException, LMISException {
for (StockMovementItem stockMovementItem : stockMovementItems) {
updateDateTimeIfEmpty(stockMovementItem);
dao.createOrUpdate(stockMovementItem);
for (LotMovementItem lotMovementItem : stockMovementItem.getLotMovementItemListWrapper()) {
Lot existingLot = lotRepository.getLotByLotNumberAndProductId(lotMovementItem.getLot().getLotNumber(), lotMovementItem.getLot().getProduct().getId());
lotMovementItem.setLot(existingLot);
lotRepository.createLotMovementItem(lotMovementItem);
}
}
return null;
}
});
}
public StockMovementItem getFirstStockMovement() throws LMISException {
return dbUtil.withDao(StockMovementItem.class, new DbUtil.Operation<StockMovementItem, StockMovementItem>() {
@Override
public StockMovementItem operate(Dao<StockMovementItem, String> dao) throws SQLException {
return dao.queryBuilder()
.orderBy("movementDate", true)
.orderBy("createdTime", true)
.queryForFirst();
}
});
}
public List<String> queryStockMovementDatesByProgram(final String programCode) {
String rawSql = "SELECT movementDate FROM stock_items s1 "
+ "JOIN stock_cards s2 ON s1.stockCard_id = s2.id "
+ "JOIN products p1 ON s2.product_id = p1.id "
+ "JOIN product_programs p2 ON p2.productCode = p1.code "
+ "JOIN programs p3 ON p2.programCode = p3.programCode "
+ "WHERE p1.isActive = 1 AND p1.isArchived = 0 AND p2.isActive = 1 AND p3.programCode = '" + programCode + "' "
+ "OR p3.parentCode = '" + programCode + "'";
final Cursor cursor = LmisSqliteOpenHelper.getInstance(LMISApp.getContext()).getWritableDatabase().rawQuery(rawSql, null);
List<String> movementDates = new ArrayList<>();
if (cursor.moveToFirst()) {
do {
movementDates.add(cursor.getString(cursor.getColumnIndexOrThrow("movementDate")));
} while (cursor.moveToNext());
}
if (!cursor.isClosed()) {
cursor.close();
}
return movementDates;
}
public Date queryEarliestStockMovementDateByProgram(final String programCode) {
Date earliestDate = null;
for (String movementDate : queryStockMovementDatesByProgram(programCode)) {
Date date = DateUtil.parseString(movementDate, DateUtil.DB_DATE_FORMAT);
if (earliestDate == null || date.before(earliestDate)) {
earliestDate = date;
}
}
return earliestDate;
}
public StockMovementItem queryFirstStockMovementByStockCardId(final long stockCardId) throws LMISException {
return dbUtil.withDao(StockMovementItem.class, new DbUtil.Operation<StockMovementItem, StockMovementItem>() {
@Override
public StockMovementItem operate(Dao<StockMovementItem, String> dao) throws SQLException {
return dao.queryBuilder()
.orderBy("movementDate", true)
.orderBy("createdTime", true)
.where()
.eq("stockCard_id", stockCardId)
.queryForFirst();
}
});
}
public List<StockMovementItem> queryStockMovementHistory(final long stockCardId, final long startIndex, final long maxRows) throws LMISException {
return dbUtil.withDao(StockMovementItem.class, new DbUtil.Operation<StockMovementItem, List<StockMovementItem>>() {
@Override
public List<StockMovementItem> operate(Dao<StockMovementItem, String> dao) throws SQLException {
return dao.queryBuilder().offset(startIndex).limit(maxRows).orderBy("movementDate", true).orderBy("createdTime", true).orderBy("id", true).where().eq("stockCard_id", stockCardId).query();
}
});
}
public List<StockMovementItem> queryStockItemsByCreatedDate(final long stockCardId, final Date periodBeginDate, final Date periodEndDate) throws LMISException {
return dbUtil.withDao(StockMovementItem.class, new DbUtil.Operation<StockMovementItem, List<StockMovementItem>>() {
@Override
public List<StockMovementItem> operate(Dao<StockMovementItem, String> dao) throws SQLException {
return dao.queryBuilder()
.orderBy("movementDate", true)
.orderBy("createdTime", true)
.where()
.eq("stockCard_id", stockCardId)
.and().gt("createdTime", periodBeginDate)//difference from the api above
.and().le("createdTime", periodEndDate)
.query();
}
});
}
public List<StockMovementItem> queryStockMovementsByMovementDate(final long stockCardId, final Date startDate, final Date endDate) throws LMISException {
return dbUtil.withDao(StockMovementItem.class, new DbUtil.Operation<StockMovementItem, List<StockMovementItem>>() {
@Override
public List<StockMovementItem> operate(Dao<StockMovementItem, String> dao) throws SQLException {
return dao.queryBuilder()
.orderBy("movementDate", true)
.orderBy("createdTime", true)
.where()
.eq("stockCard_id", stockCardId)
.and().ge("movementDate", startDate)
.and().le("movementDate", endDate)
.query();
}
});
}
public List<StockMovementItem> listLastFiveStockMovements(final long stockCardId) throws LMISException {
return dbUtil.withDao(StockMovementItem.class, new DbUtil.Operation<StockMovementItem, List<StockMovementItem>>() {
@Override
public List<StockMovementItem> operate(Dao<StockMovementItem, String> dao) throws SQLException {
return Lists.reverse(dao.queryBuilder().limit(5L).orderBy("movementDate", false).orderBy("createdTime", false).orderBy("id", false).where().eq("stockCard_id", stockCardId).query());
}
});
}
}