/* * 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.model.repository; import android.content.Context; import com.google.inject.Inject; import com.j256.ormlite.dao.Dao; import com.j256.ormlite.misc.TransactionManager; import com.j256.ormlite.stmt.Where; import org.openlmis.core.LMISApp; import org.openlmis.core.exceptions.LMISException; import org.openlmis.core.manager.SharedPreferenceMgr; import org.openlmis.core.model.BaseInfoItem; import org.openlmis.core.model.Period; import org.openlmis.core.model.ProductProgram; import org.openlmis.core.model.Program; import org.openlmis.core.model.RegimenItem; import org.openlmis.core.model.RnRForm; import org.openlmis.core.model.RnrFormItem; import org.openlmis.core.model.StockCard; import org.openlmis.core.model.StockMovementItem; import org.openlmis.core.model.helper.RnrFormHelper; import org.openlmis.core.model.service.RequisitionPeriodService; 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.base.Function; import org.roboguice.shaded.goole.common.collect.FluentIterable; import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.Callable; public class RnrFormRepository { @Inject DbUtil dbUtil; @Inject StockRepository stockRepository; @Inject RegimenRepository regimenRepository; @Inject RnrFormItemRepository rnrFormItemRepository; @Inject RegimenItemRepository regimenItemRepository; @Inject RnrFormSignatureRepository signatureRepository; @Inject BaseInfoItemRepository baseInfoItemRepository; @Inject ProductProgramRepository productProgramRepository; @Inject ProgramRepository programRepository; @Inject RnrFormHelper rnrFormHelper; GenericDao<RnRForm> genericDao; GenericDao<RnrFormItem> rnrFormItemGenericDao; private Context context; protected String programCode; @Inject private RequisitionPeriodService requisitionPeriodService; @Inject private StockMovementRepository stockMovementRepository; @Inject public RnrFormRepository(Context context) { genericDao = new GenericDao<>(RnRForm.class, context); rnrFormItemGenericDao = new GenericDao<>(RnrFormItem.class, context); this.context = context; } public RnRForm initNormalRnrForm(Date periodEndDate) throws LMISException { RnRForm rnrForm = initRnRForm(periodEndDate, RnRForm.Emergency.No); return createInitRnrForm(rnrForm); } public RnRForm initEmergencyRnrForm(Date periodEndDate, List<StockCard> stockCards) throws LMISException { RnRForm rnRForm = initRnRForm(periodEndDate, RnRForm.Emergency.Yes); rnRForm.setRnrFormItemListWrapper(generateRnrFormItems(rnRForm, stockCards)); return rnRForm; } public void create(RnRForm rnRForm) throws LMISException { genericDao.create(rnRForm); } public void createRnRsWithItems(final List<RnRForm> forms) throws LMISException { try { TransactionManager.callInTransaction(LmisSqliteOpenHelper.getInstance(context).getConnectionSource(), new Callable<Object>() { @Override public Object call() throws Exception { for (RnRForm form : forms) { createOrUpdateWithItems(form); } return null; } }); } catch (SQLException e) { throw new LMISException(e); } } public void createOrUpdateWithItems(final RnRForm form) throws LMISException { try { TransactionManager.callInTransaction(LmisSqliteOpenHelper.getInstance(context).getConnectionSource(), new Callable<Object>() { @Override public Object call() throws Exception { genericDao.createOrUpdate(form); createOrUpdateRnrWrappers(form); genericDao.refresh(form); return null; } }); } catch (SQLException e) { throw new LMISException(e); } } public boolean isPeriodUnique(final RnRForm form) { try { return null == dbUtil.withDao(RnRForm.class, new DbUtil.Operation<RnRForm, RnRForm>() { @Override public RnRForm operate(Dao<RnRForm, String> dao) throws SQLException { return dao.queryBuilder().where().eq("program_id", form.getProgram().getId()).and().eq("status", RnRForm.STATUS.AUTHORIZED).and().eq("periodBegin", form.getPeriodBegin()).and().eq("periodEnd", form.getPeriodEnd()).queryForFirst(); } }); } catch (LMISException e) { e.reportToFabric(); } return false; } public List<RnRForm> list() throws LMISException { return genericDao.queryForAll(); } public List<RnRForm> listInclude(RnRForm.Emergency includeEmergency, String programCode) throws LMISException { return list(programCode, includeEmergency.Emergency()); } public List<RnRForm> queryAllUnsyncedForms() throws LMISException { List<RnRForm> unsyncedRnr = listUnsynced(); deleteDeactivatedAndUnsupportedProductItems(unsyncedRnr); return unsyncedRnr; } public RnRForm queryUnAuthorized() throws LMISException { final Program program = programRepository.queryByCode(programCode); if (program == null) { throw new LMISException("Program cannot be null !"); } RnRForm rnRForm = dbUtil.withDao(RnRForm.class, new DbUtil.Operation<RnRForm, RnRForm>() { @Override public RnRForm operate(Dao<RnRForm, String> dao) throws SQLException { return dao.queryBuilder().where().eq("program_id", program.getId()).and().ne("status", RnRForm.STATUS.AUTHORIZED).queryForFirst(); } }); assignCategoryForRnrItems(rnRForm); return rnRForm; } public RnRForm queryRnRForm(final long id) throws LMISException { RnRForm rnRForm = dbUtil.withDao(RnRForm.class, new DbUtil.Operation<RnRForm, RnRForm>() { @Override public RnRForm operate(Dao<RnRForm, String> dao) throws SQLException { return dao.queryBuilder().where().eq("id", id).queryForFirst(); } }); assignCategoryForRnrItems(rnRForm); return rnRForm; } protected void deleteDeactivatedAndUnsupportedProductItems(List<RnRForm> rnRForms) throws LMISException { for (RnRForm rnRForm : rnRForms) { String programCode = rnRForm.getProgram().getProgramCode(); List<String> programCodes = programRepository.queryProgramCodesByProgramCodeOrParentCode(programCode); List<String> supportedProductCodes = FluentIterable.from(productProgramRepository.listActiveProductProgramsByProgramCodes(programCodes)).transform(new Function<ProductProgram, String>() { @Override public String apply(ProductProgram productProgram) { return productProgram.getProductCode(); } }).toList(); rnrFormItemRepository.deleteFormItems(rnRForm.getDeactivatedAndUnsupportedProductItems(supportedProductCodes)); } } public List<RnrFormItem> generateRnrFormItems(final RnRForm form, List<StockCard> stockCards) throws LMISException { List<RnrFormItem> rnrFormItems = new ArrayList<>(); List<String> programCodes = programRepository.queryProgramCodesByProgramCodeOrParentCode(form.getProgram().getProgramCode()); for (StockCard stockCard : stockCards) { RnrFormItem rnrFormItem = createRnrFormItemByPeriod(stockCard, form.getPeriodBegin(), form.getPeriodEnd()); rnrFormItem.setForm(form); rnrFormItems.add(rnrFormItem); rnrFormItem.setCategory(productProgramRepository.queryByCode(rnrFormItem.getProduct().getCode(), programCodes).getCategory()); } return rnrFormItems; } public void removeRnrForm(RnRForm form) throws LMISException { if (form != null) { rnrFormItemRepository.deleteFormItems(form.getRnrFormItemListWrapper()); regimenItemRepository.deleteRegimenItems(form.getRegimenItemListWrapper()); baseInfoItemRepository.batchDelete(form.getBaseInfoItemListWrapper()); signatureRepository.batchDelete(form.getSignaturesWrapper()); genericDao.delete(form); } } public boolean hasRequisitionData() { try { List<RnRForm> list = list(); if (list != null && list.size() > 0) { return true; } } catch (LMISException e) { e.reportToFabric(); } return false; } public boolean hasOldDate() { List<RnRForm> list = null; try { list = list(); } catch (LMISException e) { e.reportToFabric(); } Date dueDateShouldDataLivedInDB = DateUtil.dateMinusMonth(new Date(), SharedPreferenceMgr.getInstance().getMonthOffsetThatDefinedOldData()); if(hasRequisitionData()){ for(RnRForm rnrForm: list) { if (rnrForm.getPeriodEnd().before(dueDateShouldDataLivedInDB)) { return true; } } } return false; } protected List<RnRForm> listUnsynced() throws LMISException { return dbUtil.withDao(RnRForm.class, new DbUtil.Operation<RnRForm, List<RnRForm>>() { @Override public List<RnRForm> operate(Dao<RnRForm, String> dao) throws SQLException { return dao.queryBuilder().where().eq("synced", false).and().eq("status", RnRForm.STATUS.AUTHORIZED).query(); } }); } protected RnrFormItem createRnrFormItemByPeriod(StockCard stockCard, Date startDate, Date endDate) throws LMISException { RnrFormItem rnrFormItem = new RnrFormItem(); List<StockMovementItem> stockMovementItems = stockMovementRepository.queryStockItemsByCreatedDate(stockCard.getId(), startDate, endDate); if (stockMovementItems.isEmpty()) { rnrFormHelper.initRnrFormItemWithoutMovement(rnrFormItem, lastRnrInventory(stockCard)); } else { rnrFormItem.setInitialAmount(stockMovementItems.get(0).calculatePreviousSOH()); rnrFormHelper.assignTotalValues(rnrFormItem, stockMovementItems); } rnrFormItem.setProduct(stockCard.getProduct()); return rnrFormItem; } protected List<RegimenItem> generateRegimeItems(RnRForm form) throws LMISException { return new ArrayList<>(); } protected List<BaseInfoItem> generateBaseInfoItems(RnRForm form) { return new ArrayList<>(); } private RnRForm initRnRForm(Date periodEndDate, RnRForm.Emergency emergency) throws LMISException { final Program program = programRepository.queryByCode(programCode); if (program == null) { throw new LMISException("Program cannot be null !"); } Period period = requisitionPeriodService.generateNextPeriod(programCode, periodEndDate); return RnRForm.init(program, period, emergency.Emergency()); } private RnRForm createInitRnrForm(final RnRForm rnrForm) throws LMISException { try { TransactionManager.callInTransaction(LmisSqliteOpenHelper.getInstance(context).getConnectionSource(), new Callable<Object>() { @Override public Object call() throws Exception { create(rnrForm); List<StockCard> stockCards = stockRepository.getStockCardsBeforePeriodEnd(rnrForm); rnrFormItemRepository.batchCreateOrUpdate(generateRnrFormItems(rnrForm, stockCards)); regimenItemRepository.batchCreateOrUpdate(generateRegimeItems(rnrForm)); baseInfoItemRepository.batchCreateOrUpdate(generateBaseInfoItems(rnrForm)); genericDao.refresh(rnrForm); return null; } }); } catch (SQLException e) { throw new LMISException(e); } assignCategoryForRnrItems(rnrForm); return rnrForm; } private void assignCategoryForRnrItems(RnRForm rnrForm) throws LMISException { if (rnrForm == null || rnrForm.getRnrFormItemListWrapper() == null) { return; } List<String> programCodes = programRepository.queryProgramCodesByProgramCodeOrParentCode(programCode); for (RnrFormItem item : rnrForm.getRnrFormItemListWrapper()) { if (item.getProduct() != null) { item.setCategory(productProgramRepository.queryByCode(item.getProduct().getCode(), programCodes).getCategory()); } } } protected long lastRnrInventory(StockCard stockCard) throws LMISException { List<RnRForm> rnRForms = listInclude(RnRForm.Emergency.No, programCode); if (rnRForms.isEmpty()) { return 0; } List<RnrFormItem> rnrFormItemListWrapper = rnRForms.get(rnRForms.size() - 1).getRnrFormItemListWrapper(); for (RnrFormItem item : rnrFormItemListWrapper) { if (item.getProduct().getId() == stockCard.getProduct().getId()) { return item.getInventory(); } } return 0; } private List<RnRForm> list(String programCode, final boolean isWithEmergency) throws LMISException { final List<Long> programIds = programRepository.queryProgramIdsByProgramCodeOrParentCode(programCode); return dbUtil.withDao(RnRForm.class, new DbUtil.Operation<RnRForm, List<RnRForm>>() { @Override public List<RnRForm> operate(Dao<RnRForm, String> dao) throws SQLException { Where<RnRForm, String> where = dao.queryBuilder().orderBy("periodBegin", true).where(); where.in("program_id", programIds); if (!isWithEmergency) { where.and().eq("emergency", false); } return where.query(); } }); } public void createAndRefresh(RnRForm rnRForm) throws LMISException { create(rnRForm); genericDao.refresh(rnRForm); } private void createOrUpdateRnrWrappers(RnRForm form) throws SQLException, LMISException { rnrFormItemRepository.batchCreateOrUpdate(form.getRnrFormItemListWrapper()); signatureRepository.batchCreateOrUpdate(form.getSignaturesWrapper()); regimenItemRepository.batchCreateOrUpdate(form.getRegimenItemListWrapper()); baseInfoItemRepository.batchCreateOrUpdate(form.getBaseInfoItemListWrapper()); } public void deleteOldData() { String dueDateShouldDataLivedInDB = DateUtil.formatDate(DateUtil.dateMinusMonth(new Date(), SharedPreferenceMgr.getInstance().getMonthOffsetThatDefinedOldData()), DateUtil.DB_DATE_FORMAT); String rawSqlDeleteRnrFormItems = "DELETE FROM rnr_form_items " + "WHERE form_id IN (SELECT id FROM rnr_forms WHERE periodEnd < '" + dueDateShouldDataLivedInDB + "' );"; String rawSqlDeleteSignature = "DELETE FROM rnr_form_signature " + "WHERE form_id IN (SELECT id FROM rnr_forms WHERE periodEnd < '" + dueDateShouldDataLivedInDB + "' );"; String rawSqlDeleteRegimeItems = "DELETE FROM regime_items " + "WHERE form_id IN (SELECT id FROM rnr_forms WHERE periodEnd < '" + dueDateShouldDataLivedInDB + "' );"; String rawSqlDeleteBaseInfoItems = "DELETE FROM rnr_baseInfo_items " + "WHERE rnRForm_id IN (SELECT id FROM rnr_forms WHERE periodEnd < '" + dueDateShouldDataLivedInDB + "' );"; String rawSqlDeleteRnrForms = "DELETE FROM rnr_forms " + "WHERE periodEnd < '" + dueDateShouldDataLivedInDB + "'; "; LmisSqliteOpenHelper.getInstance(LMISApp.getContext()).getWritableDatabase().execSQL(rawSqlDeleteRnrFormItems); LmisSqliteOpenHelper.getInstance(LMISApp.getContext()).getWritableDatabase().execSQL(rawSqlDeleteBaseInfoItems); LmisSqliteOpenHelper.getInstance(LMISApp.getContext()).getWritableDatabase().execSQL(rawSqlDeleteRegimeItems); LmisSqliteOpenHelper.getInstance(LMISApp.getContext()).getWritableDatabase().execSQL(rawSqlDeleteSignature); LmisSqliteOpenHelper.getInstance(LMISApp.getContext()).getWritableDatabase().execSQL(rawSqlDeleteRnrForms); } }