diff --git a/api/src/main/java/org/openmrs/module/pharmacy/api/ProductAttributeService.java b/api/src/main/java/org/openmrs/module/pharmacy/api/ProductAttributeService.java index 637437b..71574ae 100644 --- a/api/src/main/java/org/openmrs/module/pharmacy/api/ProductAttributeService.java +++ b/api/src/main/java/org/openmrs/module/pharmacy/api/ProductAttributeService.java @@ -60,4 +60,6 @@ public interface ProductAttributeService extends OpenmrsService { ProductAttribute getOneProductAttributeByBatchNumberAndExpiryDate(String batchNumber, Date expiryDate); @Authorized(value = {PrivilegeConstants.SAVE_PRODUCT_ATTRIBUTE}) Integer purgeUnusedAttributes(); + + List getAllAttributesNotInStock(Location location, Boolean includeVoided); } diff --git a/api/src/main/java/org/openmrs/module/pharmacy/api/ProductReportService.java b/api/src/main/java/org/openmrs/module/pharmacy/api/ProductReportService.java index c3e1184..e634622 100644 --- a/api/src/main/java/org/openmrs/module/pharmacy/api/ProductReportService.java +++ b/api/src/main/java/org/openmrs/module/pharmacy/api/ProductReportService.java @@ -117,6 +117,10 @@ public interface ProductReportService extends OpenmrsService { ProductReport getLastProductReportByProductAndByDate(Location location, ProductProgram productProgram, Product product, Date reportDate, Boolean urgent); @Authorized(value = {PrivilegeConstants.VIEW_REPORT}) ProductReport getPeriodTreatedProductReportsByReportPeriodAndLocation(String operationNumber, ProductProgram program, Location childLocation, boolean isUrgent); + @Authorized(value = {PrivilegeConstants.VIEW_REPORT}) + ProductReport getLatestReportByProductAndLocationAndInventory(Location location, ProductInventory inventory); + @Authorized(value = {PrivilegeConstants.VIEW_REPORT}) + ProductReport getLatestDistributionByLocationAndInventory(Location location, Location reportLocation, ProductInventory inventory); // List getProductReportReturnDTOs(ProductReport productReport) throws APIException; // ProductReportReturnDTO getOneProductReportReturnDTO(ProductReport reception, ProductAttribute productAttribute) throws APIException; // List getProductReportListDTOs() throws APIException; diff --git a/api/src/main/java/org/openmrs/module/pharmacy/api/db/ProductAttributeDAO.java b/api/src/main/java/org/openmrs/module/pharmacy/api/db/ProductAttributeDAO.java index 2511fea..2a59945 100644 --- a/api/src/main/java/org/openmrs/module/pharmacy/api/db/ProductAttributeDAO.java +++ b/api/src/main/java/org/openmrs/module/pharmacy/api/db/ProductAttributeDAO.java @@ -41,4 +41,6 @@ public interface ProductAttributeDAO { ProductAttribute getOneProductAttributeByBatchNumber(String batchNumber, Location location); ProductAttribute getOneProductAttributeByBatchNumberAndExpiryDate(String batchNumber, Date expiryDate); Integer purgeUnusedAttributes(); + + List getAllAttributesNotInStock(Location location, Boolean includeVoided); } diff --git a/api/src/main/java/org/openmrs/module/pharmacy/api/db/ProductReportDAO.java b/api/src/main/java/org/openmrs/module/pharmacy/api/db/ProductReportDAO.java index 27b4c9b..a96bbf7 100644 --- a/api/src/main/java/org/openmrs/module/pharmacy/api/db/ProductReportDAO.java +++ b/api/src/main/java/org/openmrs/module/pharmacy/api/db/ProductReportDAO.java @@ -62,6 +62,9 @@ public interface ProductReportDAO { ProductAttributeOtherFlux getPreviousReportProductAttributeOtherFluxByLabel(Product product, String label, ProductReport report, Location location); ProductReport getLastProductReportByProductAndByDate(Location location, ProductProgram productProgram, Product product, Date reportDate, Boolean urgent); ProductReport getPeriodTreatedProductReportsByReportPeriodAndLocation(String reportPeriod, ProductProgram program, Location childLocation, boolean isUrgent); + + ProductReport getLatestReportByLocationAndInventory(Location location, ProductInventory inventory); + ProductReport getLatestDistributionByLocationAndInventory(Location location, Location reportLocation, ProductInventory inventory); // List getProductReportReturnDTOs(ProductReport productReport); // ProductReportReturnDTO getOneProductReportReturnDTO(ProductReport reception, ProductAttribute productAttribute); // List getProductReportListDTOs(); diff --git a/api/src/main/java/org/openmrs/module/pharmacy/api/db/hibernate/HibernatePharmacyDAO.java b/api/src/main/java/org/openmrs/module/pharmacy/api/db/hibernate/HibernatePharmacyDAO.java index d33875f..3e077ce 100644 --- a/api/src/main/java/org/openmrs/module/pharmacy/api/db/hibernate/HibernatePharmacyDAO.java +++ b/api/src/main/java/org/openmrs/module/pharmacy/api/db/hibernate/HibernatePharmacyDAO.java @@ -89,27 +89,9 @@ public Boolean validateOperation(ProductOperation operation) { Set fluxes = operation.getProductAttributeFluxes(); if (fluxes != null && fluxes.size() != 0) { for (ProductAttributeFlux flux : fluxes) { - Integer quantityInStock = 0; - - ProductAttributeStock attributeStock = Context.getService(ProductAttributeStockService.class) - .getOneProductAttributeStockByAttribute(flux.getProductAttribute(), operation.getLocation(), false); - if (attributeStock != null) { -// System.out.println("--------------------------------------> attribute stock found"); - quantityInStock = attributeStock.getQuantityInStock(); -// System.out.println("--------------------------------------> got quantity"); - attributeStock.setVoided(true); - attributeStock.setDateVoided(new Date()); - attributeStock.setVoidedBy(Context.getAuthenticatedUser()); - attributeStock.setVoidReason("Voided by user because not to be used"); - Context.getService(ProductAttributeStockService.class).saveProductAttributeStock(attributeStock); -// System.out.println("--------------------------------------> attribute stock voided"); - } + Integer quantity = getQuantity(operation, flux, true); - Integer quantity = operation.getIncidence().equals(Incidence.POSITIVE) ? - quantityInStock + flux.getQuantity() : - (operation.getIncidence().equals(Incidence.NEGATIVE) ? quantityInStock - flux.getQuantity() : flux.getQuantity()); - - attributeStock = new ProductAttributeStock(); + ProductAttributeStock attributeStock = new ProductAttributeStock(); attributeStock.setQuantityInStock(quantity); attributeStock.setLocation(operation.getLocation()); attributeStock.setProductAttribute(flux.getProductAttribute()); @@ -135,24 +117,9 @@ public Boolean cancelOperation(ProductOperation operation) { if (fluxes != null && fluxes.size() != 0) { for (ProductAttributeFlux flux : fluxes) { if (flux.getStatus().equals(OperationStatus.VALIDATED)) { - Integer quantityInStock = 0; - ProductAttributeStock attributeStock = Context.getService(ProductAttributeStockService.class) - .getOneProductAttributeStockByAttribute( - flux.getProductAttribute(), - operation.getLocation(), false); - if (attributeStock != null) { - quantityInStock = attributeStock.getQuantityInStock(); - attributeStock.setVoided(true); - attributeStock.setDateVoided(new Date()); - attributeStock.setVoidedBy(Context.getAuthenticatedUser()); - attributeStock.setVoidReason("Voided by user because not to be used"); - Context.getService(ProductAttributeStockService.class).saveProductAttributeStock(attributeStock); - } - Integer quantity = operation.getIncidence().equals(Incidence.POSITIVE) ? - quantityInStock - flux.getQuantity() : - (operation.getIncidence().equals(Incidence.NEGATIVE) ? quantityInStock + flux.getQuantity() : flux.getQuantity()); - - attributeStock = new ProductAttributeStock(); + Integer quantity = getQuantity(operation, flux, false); + + ProductAttributeStock attributeStock = new ProductAttributeStock(); attributeStock.setQuantityInStock(quantity); attributeStock.setLocation(operation.getLocation()); attributeStock.setProductAttribute(flux.getProductAttribute()); @@ -171,6 +138,39 @@ public Boolean cancelOperation(ProductOperation operation) { return saveProductOperation(operation) != null; } + private Integer voidPreviousStock(ProductOperation operation, ProductAttributeFlux flux) { + Integer quantityInStock = 0; + ProductAttributeStock attributeStock = Context.getService(ProductAttributeStockService.class) + .getOneProductAttributeStockByAttribute(flux.getProductAttribute(), operation.getLocation(), false); + if (attributeStock != null) { + quantityInStock = attributeStock.getQuantityInStock(); + attributeStock.setVoided(true); + attributeStock.setDateVoided(new Date()); + attributeStock.setVoidedBy(Context.getAuthenticatedUser()); + attributeStock.setVoidReason("Voided by user because not to be used"); + Context.getService(ProductAttributeStockService.class).saveProductAttributeStock(attributeStock); + } + return quantityInStock; + } + + private Integer getQuantity(ProductOperation operation, ProductAttributeFlux flux, Boolean isValidation) { + Integer quantityInStock = voidPreviousStock(operation, flux); + if (isValidation) { + if (operation.getIncidence().equals(Incidence.POSITIVE)) { + return quantityInStock + flux.getQuantity(); + } else if (operation.getIncidence().equals(Incidence.NEGATIVE)) { + return quantityInStock - flux.getQuantity(); + } + } else { + if (operation.getIncidence().equals(Incidence.POSITIVE)) { + return quantityInStock - flux.getQuantity(); + } else if (operation.getIncidence().equals(Incidence.NEGATIVE)) { + return quantityInStock + flux.getQuantity(); + } + } + return flux.getQuantity(); + } + @Override public ProductOperation getOneProductOperationById(Integer productOperationId) { return (ProductOperation) sessionFactory.getCurrentSession().get(ProductOperation.class, productOperationId); diff --git a/api/src/main/java/org/openmrs/module/pharmacy/api/db/hibernate/HibernateProductAttributeDAO.java b/api/src/main/java/org/openmrs/module/pharmacy/api/db/hibernate/HibernateProductAttributeDAO.java index 53fb322..2c7dcb9 100644 --- a/api/src/main/java/org/openmrs/module/pharmacy/api/db/hibernate/HibernateProductAttributeDAO.java +++ b/api/src/main/java/org/openmrs/module/pharmacy/api/db/hibernate/HibernateProductAttributeDAO.java @@ -128,10 +128,19 @@ public ProductAttribute getOneProductAttributeByBatchNumberAndExpiryDate(String @Override public Integer purgeUnusedAttributes() { List productAttributes = sessionFactory.getCurrentSession().createQuery("" + - "FROM ProductAttribute p WHERE p.productAttributeId NOT IN (SELECT pf.productAttribute.productAttributeId FROM ProductAttributeFlux pf)").list(); + "FROM ProductAttribute p WHERE " + + "p.productAttributeId NOT IN (SELECT pf.productAttribute.productAttributeId FROM ProductAttributeFlux pf) " + + "AND p.productAttributeId NOT IN (SELECT pof.productAttribute.productAttributeId FROM ProductAttributeOtherFlux pof) " + + "AND p.productAttributeId NOT IN (SELECT ps.productAttribute.productAttributeId FROM ProductAttributeStock ps)").list(); + Integer quantityDeleted = productAttributes.size(); for (ProductAttribute attribute : productAttributes) { removeProductAttribute(attribute); } - return productAttributes.size(); + return quantityDeleted; + } + + @Override + public List getAllAttributesNotInStock(Location location, Boolean includeVoided) { + return null; } } diff --git a/api/src/main/java/org/openmrs/module/pharmacy/api/db/hibernate/HibernateProductReportDAO.java b/api/src/main/java/org/openmrs/module/pharmacy/api/db/hibernate/HibernateProductReportDAO.java index 3998034..d4a9b19 100644 --- a/api/src/main/java/org/openmrs/module/pharmacy/api/db/hibernate/HibernateProductReportDAO.java +++ b/api/src/main/java/org/openmrs/module/pharmacy/api/db/hibernate/HibernateProductReportDAO.java @@ -18,6 +18,7 @@ import org.hibernate.Criteria; import org.hibernate.HibernateException; import org.hibernate.SessionFactory; +import org.hibernate.criterion.Criterion; import org.hibernate.criterion.Order; import org.hibernate.criterion.Restrictions; import org.openmrs.Location; @@ -29,9 +30,7 @@ import org.openmrs.module.pharmacy.dto.ProductReportLineDTO; import org.openmrs.module.pharmacy.utils.OperationUtils; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import java.util.*; /** * It is a default implementation of {@link ProductReportDAO}. @@ -103,12 +102,40 @@ public List getAllProductDistributionReports(Location location, B if (inventory == null) { return null; } else { - Criteria criteria = sessionFactory.getCurrentSession().createCriteria(ProductReport.class); - return criteria - .add(Restrictions.eq("location", location)) - .add(Restrictions.eq("voided", includeVoided)) - .add(Restrictions.ge("operationDate", inventory.getOperationDate())) - .add(Restrictions.isNotNull("reportLocation")).list(); + List productReports = new ArrayList<>(); + List locations = OperationUtils.getUserLocations(); + for (Location l : locations) { + List programs = OperationUtils.getLocationPrograms(l); + for (ProductProgram program : programs) { + inventory = Context.getService(ProductInventoryService.class).getLastProductInventory(location, program, InventoryType.TOTAL); + if (inventory != null) { + Criteria criteria = sessionFactory.getCurrentSession().createCriteria(ProductReport.class); + List reports = criteria + .add(Restrictions.eq("location", location)) + .add(Restrictions.eq("voided", includeVoided)) + .add(Restrictions.ge("operationDate", inventory.getOperationDate())) + .add(Restrictions.isNotNull("reportLocation")).list(); + + if (reports != null && !reports.isEmpty()) { + List reportToImport = new ArrayList<>(); + for (ProductReport report : reports) { + if (!productReports.contains(report)) { + reportToImport.add(report); + } + } + productReports.addAll(reportToImport); + } + } + } + + } + return productReports; +// Criteria criteria = sessionFactory.getCurrentSession().createCriteria(ProductReport.class); +// return criteria +// .add(Restrictions.eq("location", location)) +// .add(Restrictions.eq("voided", includeVoided)) +// .add(Restrictions.ge("operationDate", inventory.getOperationDate())) +// .add(Restrictions.isNotNull("reportLocation")).list(); } } @@ -116,24 +143,58 @@ public List getAllProductDistributionReports(Location location, B @Override public List getAllSubmittedChildProductReports(Location location, Boolean includeVoided) { ProductInventory inventory = getFirstInventoryDateOfLastPeriod(location); + List productReports = new ArrayList<>(); if (inventory == null) { return null; } else { + List locations = OperationUtils.getUserLocations(); + for (Location l : locations) { + List programs = OperationUtils.getLocationPrograms(l); + for (ProductProgram program : programs) { + inventory = Context.getService(ProductInventoryService.class).getLastProductInventory(location, program, InventoryType.TOTAL); + if (inventory != null) { + List reports = (List) sessionFactory.getCurrentSession().createQuery( + "SELECT r FROM ProductReport r " + + "WHERE r.operationDate >= :operationDate " + + "AND ((r.location = :location AND r.reportLocation IS NOT NULL AND r.reportLocation = :locations) OR (r.location = :locations)) " + + "AND r.productProgram = :program " + + "AND (r.operationStatus = :submitted OR r.operationStatus = :validated OR r.operationStatus = :treated OR r.operationStatus = :awaitingTreatment) " + + "AND r.voided = :voided") + .setParameter("operationDate", inventory.getOperationDate()) + .setParameter("location", location) + .setParameter("locations", l) + .setParameter("program", program) +// .setParameterList("locations", location.getChildLocations()) + .setParameter("submitted", OperationStatus.SUBMITTED) + .setParameter("validated", OperationStatus.VALIDATED) + .setParameter("treated", OperationStatus.TREATED) + .setParameter("awaitingTreatment", OperationStatus.AWAITING_TREATMENT) + .setParameter("voided", includeVoided) + .list(); + + if (reports != null && !reports.isEmpty()) { + productReports.addAll(reports); + } + } + + } + } + return productReports; // System.out.println("------------------------------------> Inventory date : " + OperationUtils.formatDate(inventory.getOperationDate())); - return (List) sessionFactory.getCurrentSession().createQuery( - "SELECT r FROM ProductReport r " + - "WHERE r.operationDate >= :operationDate " + - "AND ((r.location = :location AND r.reportLocation IS NOT NULL AND r.reportLocation IN (:locations)) OR (r.location IN (:locations))) " + - "AND (r.operationStatus = :submitted OR r.operationStatus = :validated OR r.operationStatus = :treated) " + - "AND r.voided = :voided") - .setParameter("operationDate", inventory.getOperationDate()) - .setParameter("location", location) - .setParameterList("locations", location.getChildLocations()) - .setParameter("submitted", OperationStatus.SUBMITTED) - .setParameter("validated", OperationStatus.VALIDATED) - .setParameter("treated", OperationStatus.TREATED) - .setParameter("voided", includeVoided) - .list(); +// return (List) sessionFactory.getCurrentSession().createQuery( +// "SELECT r FROM ProductReport r " + +// "WHERE r.operationDate >= :operationDate " + +// "AND ((r.location = :location AND r.reportLocation IS NOT NULL AND r.reportLocation IN (:locations)) OR (r.location IN (:locations))) " + +// "AND (r.operationStatus = :submitted OR r.operationStatus = :validated OR r.operationStatus = :treated) " + +// "AND r.voided = :voided") +// .setParameter("operationDate", inventory.getOperationDate()) +// .setParameter("location", location) +// .setParameterList("locations", location.getChildLocations()) +// .setParameter("submitted", OperationStatus.SUBMITTED) +// .setParameter("validated", OperationStatus.VALIDATED) +// .setParameter("treated", OperationStatus.TREATED) +// .setParameter("voided", includeVoided) +// .list(); } // Criteria criteria = sessionFactory.getCurrentSession().createCriteria(ProductReport.class); // if (location.getChildLocations() != null) { @@ -1031,205 +1092,35 @@ public ProductReport getPeriodTreatedProductReportsByReportPeriodAndLocation(Str .add(Restrictions.eq("isUrgent", isUrgent)).setMaxResults(1).uniqueResult(); } + @Override + public ProductReport getLatestReportByLocationAndInventory(Location location, ProductInventory inventory) { + Criteria criteria = sessionFactory.getCurrentSession().createCriteria(ProductReport.class); + return (ProductReport) criteria + .add(Restrictions.eq("location", location)) + .add(Restrictions.eq("productProgram", inventory.getProductProgram())) + .add(Restrictions.or( + Restrictions.eq("operationStatus", OperationStatus.SUBMITTED), + Restrictions.eq("operationStatus", OperationStatus.VALIDATED))) + .add(Restrictions.eq("isUrgent", inventory.getInventoryType().equals(InventoryType.PARTIAL))) + .addOrder(Order.desc("operationDate")) + .setMaxResults(1).uniqueResult(); + } -// @SuppressWarnings("unchecked") -// @Override -// public List getProductReportReturnDTOs(ProductReport productReport) { -// String sqlQuery = -// "SELECT " + -// " ppaf.product_attribute_flux_id as productAttributeFluxId, " + -// " ppr.product_operation_id as productOperationId, " + -// " pp.product_id as productId, " + -// " pp.code as code, " + -// " pp.retail_name as retailName, " + -// " pp.wholesale_name as wholesaleName, " + -// " pp.unit_conversion as unitConversion, " + -// " ppu.name as retailUnit, " + -// " ppu2.name as wholesaleUnit, " + -// " ppa.batch_number as batchNumber, " + -// " ppa.expiry_date as expiryDate, " + -// " ppaf.quantity as quantityToReturn, " + -// " ppo.quantityReceived, " + -// " ppas.quantity_in_stock as quantityInStock, " + -// " ppaf.observation as observation, " + -// " ppaf.date_created as dateCreated " + -// "FROM (SELECT o.product_operation_id, operation_number FROM pharmacy_product_reception r, pharmacy_product_operation o WHERE r.product_operation_id = o.product_operation_id AND r.product_operation_id = :productOperationId) ppr " + -// " LEFT JOIN pharmacy_product_attribute_flux ppaf on ppr.product_operation_id = ppaf.operation_id " + -// " LEFT JOIN ( " + -// " SELECT operation_number, quantity quantityReceived, product_attribute_id " + -// " FROM pharmacy_product_operation o " + -// " LEFT JOIN pharmacy_product_attribute_flux f ON o.product_operation_id = f.operation_id " + -// " WHERE o.incidence = 1 AND operation_number = :operationNumber " + -// " ) ppo ON ppo.operation_number = ppr.operation_number AND ppo.product_attribute_id = ppaf.product_attribute_id " + -// " LEFT JOIN pharmacy_product_attribute ppa on ppa.product_attribute_id = ppo.product_attribute_id " + -// " LEFT JOIN pharmacy_product_attribute_stock ppas on ppo.product_attribute_id = ppas.product_attribute_id " + -// " LEFT JOIN pharmacy_product pp ON ppa.product_id = pp.product_id " + -// " LEFT JOIN pharmacy_product_unit ppu on pp.product_retail_unit = ppu.product_unit_id " + -// " LEFT JOIN pharmacy_product_unit ppu2 on pp.product_wholesale_unit = ppu2.product_unit_id " + -// "WHERE ppaf.product_attribute_flux_id IS NOT NULL ORDER BY ppaf.date_created DESC"; -// -// Query query = sessionFactory.getCurrentSession().createSQLQuery(sqlQuery) -// .addScalar("productAttributeFluxId", StandardBasicTypes.INTEGER) -// .addScalar("productOperationId", StandardBasicTypes.INTEGER) -// .addScalar("productId", StandardBasicTypes.INTEGER) -// .addScalar("code", StandardBasicTypes.STRING) -// .addScalar("retailName", StandardBasicTypes.STRING) -// .addScalar("wholesaleName", StandardBasicTypes.STRING) -// .addScalar("retailUnit", StandardBasicTypes.STRING) -// .addScalar("wholesaleUnit", StandardBasicTypes.STRING) -// .addScalar("batchNumber", StandardBasicTypes.STRING) -// .addScalar("expiryDate", StandardBasicTypes.DATE) -// .addScalar("unitConversion", StandardBasicTypes.DOUBLE) -// .addScalar("quantityReceived", StandardBasicTypes.INTEGER) -// .addScalar("quantityInStock", StandardBasicTypes.INTEGER) -// .addScalar("quantityToReturn", StandardBasicTypes.INTEGER) -// .addScalar("observation", StandardBasicTypes.STRING) -// .addScalar("dateCreated", StandardBasicTypes.DATE) -// .setParameter("productOperationId", productReport.getProductOperationId()) -// .setParameter("operationNumber", productReport.getOperationNumber()) -// .setResultTransformer(new AliasToBeanResultTransformer(ProductReportReturnDTO.class)); -// try { -// return query.list(); -// } catch (HibernateException e) { -// System.out.println(e.getMessage()); -// } -// return null; -// } -// -// @Override -// public ProductReportReturnDTO getOneProductReportReturnDTO(ProductReport reception, ProductAttribute productAttribute) { -// String sqlQuery = -// "SELECT " + -// " ppaf.product_attribute_flux_id as productAttributeFluxId, " + -// " ppr.product_operation_id as productOperationId, " + -// " pp.product_id as productId, " + -// " pp.code as code, " + -// " pp.retail_name as retailName, " + -// " pp.wholesale_name as wholesaleName, " + -// " pp.unit_conversion as unitConversion, " + -// " ppu.name as retailUnit, " + -// " ppu2.name as wholesaleUnit, " + -// " ppa.batch_number as batchNumber, " + -// " ppa.expiry_date as expiryDate, " + -// " ppaf.quantity as quantityToReturn, " + -// " ppo.quantityReceived, " + -// " ppas.quantity_in_stock as quantityInStock, " + -// " ppaf.observation as observation, " + -// " ppaf.date_created as dateCreated " + -// "FROM (SELECT o.product_operation_id, operation_number FROM pharmacy_product_reception r, pharmacy_product_operation o WHERE r.product_operation_id = o.product_operation_id AND r.product_operation_id = :productOperationId) ppr " + -// " LEFT JOIN pharmacy_product_attribute_flux ppaf on ppr.product_operation_id = ppaf.operation_id " + -// " LEFT JOIN ( " + -// " SELECT operation_number, quantity quantityReceived, product_attribute_id " + -// " FROM pharmacy_product_operation o " + -// " LEFT JOIN pharmacy_product_attribute_flux f ON o.product_operation_id = f.operation_id " + -// " WHERE o.incidence = 1 AND operation_number = :operationNumber " + -// " ) ppo ON ppo.operation_number = ppr.operation_number " + -// " LEFT JOIN pharmacy_product_attribute ppa on ppa.product_attribute_id = ppo.product_attribute_id " + -// " LEFT JOIN pharmacy_product_attribute_stock ppas on ppo.product_attribute_id = ppas.product_attribute_id " + -// " LEFT JOIN pharmacy_product pp ON ppa.product_id = pp.product_id " + -// " LEFT JOIN pharmacy_product_unit ppu on pp.product_retail_unit = ppu.product_unit_id " + -// " LEFT JOIN pharmacy_product_unit ppu2 on pp.product_wholesale_unit = ppu2.product_unit_id " + -// " WHERE ppo.product_attribute_id = :productAttributeId"; -// -// Query query = sessionFactory.getCurrentSession().createSQLQuery(sqlQuery) -// .addScalar("productAttributeFluxId", StandardBasicTypes.INTEGER) -// .addScalar("productOperationId", StandardBasicTypes.INTEGER) -// .addScalar("productId", StandardBasicTypes.INTEGER) -// .addScalar("code", StandardBasicTypes.STRING) -// .addScalar("retailName", StandardBasicTypes.STRING) -// .addScalar("wholesaleName", StandardBasicTypes.STRING) -// .addScalar("retailUnit", StandardBasicTypes.STRING) -// .addScalar("wholesaleUnit", StandardBasicTypes.STRING) -// .addScalar("batchNumber", StandardBasicTypes.STRING) -// .addScalar("expiryDate", StandardBasicTypes.DATE) -// .addScalar("unitConversion", StandardBasicTypes.DOUBLE) -// .addScalar("quantityReceived", StandardBasicTypes.INTEGER) -// .addScalar("quantityInStock", StandardBasicTypes.INTEGER) -// .addScalar("quantityToReturn", StandardBasicTypes.INTEGER) -// .addScalar("observation", StandardBasicTypes.STRING) -// .addScalar("dateCreated", StandardBasicTypes.DATE) -// .setParameter("productOperationId", reception.getProductOperationId()) -// .setParameter("productAttributeId", productAttribute.getProductAttributeId()) -// .setParameter("operationNumber", reception.getOperationNumber()) -// .setResultTransformer(new AliasToBeanResultTransformer(ProductReportReturnDTO.class)); -// try { -// return (ProductReportReturnDTO) query.uniqueResult(); -// } catch (HibernateException e) { -// System.out.println(e.getMessage()); -// } -// return null; -// } -// -// -// @SuppressWarnings("unchecked") -// @Override -// public List getProductReportListDTOs() { -// String sqlQuery = -// "SELECT " + -// " ppop.product_operation_id productOperationId, " + -// " ppop.operation_date operationDate, " + -// " pps.name productSupplier, " + -// " ppp.name programName, " + -// " operation_number operationNumber, " + -// " ppon.product_operation_id productReturnedOperationId, " + -// " IF((ppon.product_operation_id IS NULL OR (ppon.product_operation_id IS NOT NULL AND ppon.operation_status <> 2)) AND i.operation_date <= ppop.operation_date, 1, 0) canReturn, " + -// " IF(ppop.operation_status = 0, 'AWAITING_VALIDATION', " + -// " IF(ppop.operation_status = 1, 'DISABLED', " + -// " IF(ppop.operation_status = 2, 'VALIDATED', " + -// " IF(ppop.operation_status = 3, 'NOT_COMPLETED', NULL)) )) operationStatus, " + -// " IF(ppon.operation_status = 0, 'AWAITING_VALIDATION', " + -// " IF(ppon.operation_status = 1, 'DISABLED', " + -// " IF(ppon.operation_status = 2, 'VALIDATED', " + -// " IF(ppon.operation_status = 3, 'NOT_COMPLETED', NULL)) )) productReturnedOperationStatus, " + -// " IF(reception_mode = 0, 'RETAIL', " + -// " IF(reception_mode = 1, 'WHOLESALE', NULL)) receptionMode, " + -// " numberOfLine " + -// "FROM " + -// " ( " + -// " SELECT ppr.product_operation_id, operation_date, product_supplier_id, operation_number, program_id, operation_status, incidence, location_id, reception_mode " + -// " FROM pharmacy_product_reception ppr, pharmacy_product_operation ppo " + -// " WHERE ppr.product_operation_id = ppo.product_operation_id AND incidence = 1 AND location_id = :locationId " + -// " ) ppop " + -// " LEFT JOIN pharmacy_product_supplier pps ON pps.product_supplier_id = ppop.product_supplier_id " + -// " LEFT JOIN pharmacy_product_program ppp ON ppp.product_program_id = ppop.program_id " + -// "LEFT JOIN " + -// " ( " + -// " SELECT ppr.product_operation_id, operation_number returnedOperationNumber, program_id, location_id, operation_status " + -// " FROM pharmacy_product_reception ppr, pharmacy_product_operation ppo " + -// " WHERE ppr.product_operation_id = ppo.product_operation_id AND incidence = 0 " + -// " ) ppon " + -// "ON ppon.returnedOperationNumber = ppop.operation_number AND ppop.program_id = ppon.program_id AND ppon.location_id = ppop.location_id " + -// "LEFT JOIN ( " + -// " SELECT " + -// " ppo.operation_date, program_id " + -// " FROM pharmacy_product_inventory ppi, pharmacy_product_operation ppo " + -// " WHERE " + -// " ppi.product_operation_id = ppo.product_operation_id AND " + -// " ppo.operation_date = (SELECT MAX(operation_date) FROM pharmacy_product_operation po, pharmacy_product_inventory pi WHERE pi.product_operation_id = po.product_operation_id AND ppo.program_id = po.program_id AND po.location_id = :locationId " + -// " )) i ON i.program_id = ppop.program_id " + -// "LEFT JOIN (SELECT COUNT(*) numberOfLine, operation_id FROM pharmacy_product_attribute_flux GROUP BY operation_id) ppaf ON operation_id = ppop.product_operation_id"; -// -// Query query = sessionFactory.getCurrentSession().createSQLQuery(sqlQuery) -// .addScalar("productOperationId", StandardBasicTypes.INTEGER) -// .addScalar("productReturnedOperationId", StandardBasicTypes.INTEGER) -// .addScalar("operationDate", StandardBasicTypes.DATE) -// .addScalar("productSupplier", StandardBasicTypes.STRING) -// .addScalar("programName", StandardBasicTypes.STRING) -// .addScalar("operationNumber", StandardBasicTypes.STRING) -// .addScalar("productReturnedOperationId", StandardBasicTypes.INTEGER) -// .addScalar("canReturn", StandardBasicTypes.BOOLEAN) -// .addScalar("operationStatus", StandardBasicTypes.STRING) -// .addScalar("productReturnedOperationStatus", StandardBasicTypes.STRING) -// .addScalar("receptionMode", StandardBasicTypes.STRING) -// .addScalar("numberOfLine", StandardBasicTypes.INTEGER) -// .setParameter("locationId", OperationUtils.getUserLocation()) -// .setResultTransformer(new AliasToBeanResultTransformer(ProductReportListDTO.class)); -// try { -// return query.list(); -// } catch (HibernateException e) { -// System.out.println(e.getMessage()); -// } -// return null; -// } - + @Override + public ProductReport getLatestDistributionByLocationAndInventory(Location location, Location reportLocation, ProductInventory inventory) { + Criteria criteria = sessionFactory.getCurrentSession().createCriteria(ProductReport.class); + return (ProductReport) criteria + .add(Restrictions.eq("location", location)) + .add(Restrictions.eq("reportLocation", reportLocation)) + .add(Restrictions.eq("productProgram", inventory.getProductProgram())) + .add(Restrictions.in("operationStatus", Arrays.asList(OperationStatus.VALIDATED, OperationStatus.TREATED))) +// .add(Restrictions.or( +// Restrictions.eq("operationStatus", OperationStatus.SUBMITTED), +// Restrictions.eq("operationStatus", OperationStatus.VALIDATED), +// Restrictions.eq("operationStatus", OperationStatus.VALIDATED) +// ) + .add(Restrictions.eq("isUrgent", inventory.getInventoryType().equals(InventoryType.PARTIAL))) + .addOrder(Order.desc("operationDate")) + .setMaxResults(1).uniqueResult(); + } } diff --git a/api/src/main/java/org/openmrs/module/pharmacy/api/impl/ProductAttributeServiceImpl.java b/api/src/main/java/org/openmrs/module/pharmacy/api/impl/ProductAttributeServiceImpl.java index 3fe1b55..3f0d222 100644 --- a/api/src/main/java/org/openmrs/module/pharmacy/api/impl/ProductAttributeServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/pharmacy/api/impl/ProductAttributeServiceImpl.java @@ -108,4 +108,9 @@ public Integer purgeUnusedAttributes() { return dao.purgeUnusedAttributes(); } + @Override + public List getAllAttributesNotInStock(Location location, Boolean includeVoided) { + return dao.getAllAttributesNotInStock(location, includeVoided); + } + } diff --git a/api/src/main/java/org/openmrs/module/pharmacy/api/impl/ProductReportServiceImpl.java b/api/src/main/java/org/openmrs/module/pharmacy/api/impl/ProductReportServiceImpl.java index a23a6a2..2e3fb07 100644 --- a/api/src/main/java/org/openmrs/module/pharmacy/api/impl/ProductReportServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/pharmacy/api/impl/ProductReportServiceImpl.java @@ -233,6 +233,16 @@ public ProductReport getPeriodTreatedProductReportsByReportPeriodAndLocation(Str return dao.getPeriodTreatedProductReportsByReportPeriodAndLocation(reportPeriod, program, childLocation, isUrgent); } + @Override + public ProductReport getLatestReportByProductAndLocationAndInventory(Location location, ProductInventory inventory) { + return dao.getLatestReportByLocationAndInventory(location, inventory); + } + + @Override + public ProductReport getLatestDistributionByLocationAndInventory(Location location, Location reportLocation, ProductInventory inventory) { + return dao.getLatestDistributionByLocationAndInventory(location, reportLocation, inventory); + } + // // @Override // public List getProductReportReturnDTOs(ProductReport productReport) { diff --git a/api/src/main/java/org/openmrs/module/pharmacy/forms/distribution/DistributionAttributeFluxForm.java b/api/src/main/java/org/openmrs/module/pharmacy/forms/distribution/DistributionAttributeFluxForm.java index 98acfbf..7affcd2 100644 --- a/api/src/main/java/org/openmrs/module/pharmacy/forms/distribution/DistributionAttributeFluxForm.java +++ b/api/src/main/java/org/openmrs/module/pharmacy/forms/distribution/DistributionAttributeFluxForm.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; public class DistributionAttributeFluxForm extends ProductAttributeFluxForm { private Integer initialQuantity; @@ -20,6 +21,7 @@ public class DistributionAttributeFluxForm extends ProductAttributeFluxForm { private Integer numDaysOfRupture; private Integer quantityDistributed2monthAgo; private Integer quantityDistributed1monthAgo; + private ProductReport latestReport; public DistributionAttributeFluxForm() { } @@ -96,10 +98,19 @@ public void setQuantityDistributed1monthAgo(Integer quantityDistributed1monthAgo this.quantityDistributed1monthAgo = quantityDistributed1monthAgo; } + public ProductReport getLatestReport() { + return latestReport; + } + + public void setLatestReport(ProductReport latestReport) { + this.latestReport = latestReport; + } + public List getAllOtherFluxes() { List otherFluxes = new ArrayList<>(); Product product = productService().getOneProductById(getProductId()); if (product != null) { + otherFluxes.add(createProductAttributeOtherFlux(product, getInitialQuantity() == null ? 0.0 : getInitialQuantity().doubleValue(), "SI")); if (getReceivedQuantity() == null) { diff --git a/api/src/main/java/org/openmrs/module/pharmacy/utils/OperationUtils.java b/api/src/main/java/org/openmrs/module/pharmacy/utils/OperationUtils.java index 027991a..6b2380d 100644 --- a/api/src/main/java/org/openmrs/module/pharmacy/utils/OperationUtils.java +++ b/api/src/main/java/org/openmrs/module/pharmacy/utils/OperationUtils.java @@ -21,13 +21,14 @@ public static Boolean validateOperation(ProductOperation operation) { } public static void emptyStock(Location location, ProductProgram productProgram) { - List stocks = stockService().getAllProductAttributeStocks(location, false); - for (ProductAttributeStock stock : stocks) { - if (productProgram.getProducts().contains(stock.getProductAttribute().getProduct())) { - stock.setQuantityInStock(0); - stockService().saveProductAttributeStock(stock); - } - } + attributeService().purgeUnusedAttributes(); +// List stocks = stockService().getAllProductAttributeStocks(location, false); +// for (ProductAttributeStock stock : stocks) { +// if (productProgram.getProducts().contains(stock.getProductAttribute().getProduct())) { +// stock.setQuantityInStock(0); +// stockService().saveProductAttributeStock(stock); +// } +// } } public static Boolean cancelOperation(ProductOperation operation) { @@ -69,6 +70,10 @@ private static ProductAttributeStockService stockService() { return Context.getService(ProductAttributeStockService.class); } + private static ProductAttributeService attributeService() { + return Context.getService(ProductAttributeService.class); + } + public static Location getUserLocation() { if (Context.getUserContext().getLocation() != null) { return Context.getUserContext().getLocation(); @@ -870,4 +875,24 @@ public static String formatDate(Date date) { DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.DEFAULT, locale); return dateFormat.format(date); } + + public static ProductAttributeOtherFlux getLastReportOtherFluxByLabel(String label, Product product, ProductReport report) { + Set otherFluxes = report.getProductAttributeOtherFluxes(); + for (ProductAttributeOtherFlux otherFlux : report.getProductAttributeOtherFluxes()) { + if (otherFlux.getProduct() != null && otherFlux.getLabel().equals(label) && otherFlux.getProduct().equals(product)) { + return otherFlux; + } + } + return null; + } + + public static ProductAttributeFlux getLastDistributionFluxByLabel(Product product, ProductReport report) { + for (ProductAttributeFlux flux : report.getProductAttributeFluxes()) { + if (flux.getProductWithAttribute() != null && + flux.getProductWithAttribute().contains(product.getRetailName())) { + return flux; + } + } + return null; + } } diff --git a/omod/src/main/java/org/openmrs/module/pharmacy/web/controller/PharmacyProductDistributionManageController.java b/omod/src/main/java/org/openmrs/module/pharmacy/web/controller/PharmacyProductDistributionManageController.java index 3ac5e1b..2a45755 100644 --- a/omod/src/main/java/org/openmrs/module/pharmacy/web/controller/PharmacyProductDistributionManageController.java +++ b/omod/src/main/java/org/openmrs/module/pharmacy/web/controller/PharmacyProductDistributionManageController.java @@ -237,6 +237,20 @@ public String editFlux(ModelMap modelMap, distributionAttributeFluxForm = new DistributionAttributeFluxForm(); distributionAttributeFluxForm.setProductOperationId(productDistribution.getProductOperationId()); } + ProductInventory latestInventory = inventoryService().getLastProductInventory( + productDistribution.getReportLocation(), + productDistribution.getProductProgram(), + productDistribution.getUrgent() ? InventoryType.PARTIAL : InventoryType.TOTAL + ); + if (latestInventory != null) { + ProductReport report = reportService().getLatestReportByProductAndLocationAndInventory( + productDistribution.getReportLocation(), + latestInventory); + if (report != null) { + distributionAttributeFluxForm.setLatestReport(report); + } + } + modelMappingForView(modelMap, distributionAttributeFluxForm, productDistribution, slip); } return null; diff --git a/omod/src/main/java/org/openmrs/module/pharmacy/web/controller/PharmacyProductInventoryManageController.java b/omod/src/main/java/org/openmrs/module/pharmacy/web/controller/PharmacyProductInventoryManageController.java index 9aadb18..e73a8d9 100644 --- a/omod/src/main/java/org/openmrs/module/pharmacy/web/controller/PharmacyProductInventoryManageController.java +++ b/omod/src/main/java/org/openmrs/module/pharmacy/web/controller/PharmacyProductInventoryManageController.java @@ -367,7 +367,9 @@ public String validate(HttpServletRequest request, ProductMovementEntry movementEntry = new ProductMovementEntry(); for (ProductAttributeFlux flux : operation.getProductAttributeFluxes()) { - ProductAttributeOtherFlux otherFlux = attributeFluxService().getOneProductAttributeOtherFluxByAttributeAndOperation(flux.getProductAttribute(), operation, operation.getLocation()); + ProductAttributeOtherFlux otherFlux = attributeFluxService().getOneProductAttributeOtherFluxByAttributeAndOperation( + flux.getProductAttribute(), operation, operation.getLocation() + ); if (otherFlux == null) { otherFlux = new ProductAttributeOtherFlux(); otherFlux.setProductOperation(operation);