Skip to content

Commit

Permalink
TRUNK-4129 Modify datatype of drug_order.quantity column and add
Browse files Browse the repository at this point in the history
quantity_units column to drug_order
  • Loading branch information
rkorytkowski authored and wluyima committed Dec 19, 2013
1 parent a2e4eb1 commit 2e3c7cf
Show file tree
Hide file tree
Showing 7 changed files with 251 additions and 5 deletions.
25 changes: 22 additions & 3 deletions api/src/main/java/org/openmrs/DrugOrder.java
Expand Up @@ -42,7 +42,9 @@ public enum DosingType {

private Boolean asNeeded = false;

private Integer quantity;
private Double quantity;

private Concept quantityUnits;

private Drug drug;

Expand Down Expand Up @@ -90,6 +92,7 @@ protected DrugOrder copyHelper(DrugOrder target) {
target.asNeeded = getAsNeeded();
target.asNeededCondition = getAsNeededCondition();
target.quantity = getQuantity();
target.quantityUnits = getQuantityUnits();
target.drug = getDrug();
target.dosingType = getDosingType();
target.dosingInstructions = getDosingInstructions();
Expand Down Expand Up @@ -207,7 +210,7 @@ public void setComplex(Boolean complex) {
*
* @return quantity
*/
public Integer getQuantity() {
public Double getQuantity() {
return this.quantity;
}

Expand All @@ -216,10 +219,26 @@ public Integer getQuantity() {
*
* @param quantity
*/
public void setQuantity(Integer quantity) {
public void setQuantity(Double quantity) {
this.quantity = quantity;
}

/**
* @since 1.10
* @return concept
*/
public Concept getQuantityUnits() {
return quantityUnits;
}

/**
* @since 1.10
* @param quantityUnits
*/
public void setQuantityUnits(Concept quantityUnits) {
this.quantityUnits = quantityUnits;
}

/**
* Gets the drug
*
Expand Down
55 changes: 55 additions & 0 deletions api/src/main/java/org/openmrs/util/DatabaseUtil.java
Expand Up @@ -151,4 +151,59 @@ public static List<List<Object>> executeSQL(Connection conn, String sql, boolean

return results;
}

/**
* Returns conceptId for the given units from OpenmrsConstants#GP_ORDER_ENTRY_UNITS_TO_CONCEPTS_MAPPINGS
* global property.
*
* @param connection
* @param units
* @return conceptId
* @throws DAOException
* @should return concept_id for drug_order_quantity_units
* @should fail if units is not specified
*/
public static Integer getConceptIdForUnits(Connection connection, String units) throws DAOException {
PreparedStatement unitsToConceptsQuery;
try {
unitsToConceptsQuery = connection
.prepareStatement("select property_value from global_property where property = ?");
unitsToConceptsQuery.setString(1, OpenmrsConstants.GP_ORDER_ENTRY_UNITS_TO_CONCEPTS_MAPPINGS);
ResultSet unitsToConceptsResult = unitsToConceptsQuery.executeQuery();
if (!unitsToConceptsResult.next()) {
throw new DAOException(
OpenmrsConstants.GP_ORDER_ENTRY_UNITS_TO_CONCEPTS_MAPPINGS
+ " global property must be specified before upgrading. Please refer to upgrade instructions for more details.");
}

String unitsToConceptsGP = unitsToConceptsResult.getString(1);
String[] unitsToConcepts = unitsToConceptsGP.split(",");
for (String unitsToConcept : unitsToConcepts) {
if (unitsToConcept.startsWith(units)) {
String concept = unitsToConcept.substring(units.length() + 1);// '+ 1' stands for ':'

if (concept.toLowerCase().equals("null")) {
return null;
}

try {
return Integer.valueOf(concept);
}
catch (NumberFormatException e) {
throw new DAOException(OpenmrsConstants.GP_ORDER_ENTRY_UNITS_TO_CONCEPTS_MAPPINGS
+ " global property contains invalid mapping from " + units + " to concept ID " + concept
+ ". ID must be an integer or null. Please refer to upgrade instructions for more details.",
e);
}
}
}
}
catch (SQLException e) {
throw new DAOException(e);
}

throw new DAOException(OpenmrsConstants.GP_ORDER_ENTRY_UNITS_TO_CONCEPTS_MAPPINGS
+ " global property does not have mapping for " + units
+ ". Please refer to upgrade instructions for more details.");
}
}
4 changes: 3 additions & 1 deletion api/src/main/java/org/openmrs/util/OpenmrsConstants.java
Expand Up @@ -1052,10 +1052,12 @@ public static final Collection<String> AUTO_ROLES() {

public static final String GLOBAL_PROPERTY_NEXT_ORDER_NUMBER = "orderEntry.nextOrderNumber";

public static final String GP_ORDER_ENTRY_UNITS_TO_CONCEPTS_MAPPINGS = "orderEntry.unitsToConceptsMappings";

/**
* At OpenMRS startup these global properties/default values/descriptions are inserted into the
* database if they do not exist yet.
*
*
* @return List<GlobalProperty> of the core global properties
*/
public static final List<GlobalProperty> CORE_GLOBAL_PROPERTIES() {
Expand Down
@@ -0,0 +1,80 @@
/**
* The contents of this file are subject to the OpenMRS Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://license.openmrs.org
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/
package org.openmrs.util.databasechange;

import liquibase.change.custom.CustomTaskChange;
import liquibase.database.Database;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.CustomChangeException;
import liquibase.exception.DatabaseException;
import liquibase.exception.SetupException;
import liquibase.exception.ValidationErrors;
import liquibase.resource.ResourceAccessor;
import org.openmrs.util.DatabaseUtil;
import org.openmrs.util.OpenmrsConstants;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;

/**
* Applies quantity units to drug orders created pre 1.10.x based on a concept specified in a global property.
*
* @see OpenmrsConstants#GP_ORDER_ENTRY_UNITS_TO_CONCEPTS_MAPPINGS
*/
public class MigrateDrugOrderQuantityToCodedQuantityUnitsChangeset implements CustomTaskChange {

@Override
public void execute(Database database) throws CustomChangeException {
JdbcConnection connection = (JdbcConnection) database.getConnection();

Integer conceptId = DatabaseUtil.getConceptIdForUnits(connection.getUnderlyingConnection(),
"drug_order_quantity_units");

try {
PreparedStatement update = connection
.prepareStatement("update drug_order set quantity_units = ? where quantity_units is NULL");
if (conceptId == null) {
update.setNull(1, Types.INTEGER);
} else {
update.setInt(1, conceptId);
}
update.executeUpdate();
}
catch (DatabaseException e) {
throw new CustomChangeException(e);
}
catch (SQLException e) {
throw new CustomChangeException(e);
}
}

@Override
public String getConfirmationMessage() {
return "Finished migrating drug order quantity to coded quantity units";
}

@Override
public void setUp() throws SetupException {
}

@Override
public void setFileOpener(ResourceAccessor resourceAccessor) {
}

@Override
public ValidationErrors validate(Database database) {
return null;
}
}
31 changes: 31 additions & 0 deletions api/src/main/resources/liquibase-update-to-latest.xml
Expand Up @@ -6659,4 +6659,35 @@
referencedTableName="concept" referencedColumnNames="concept_id" />
</changeSet>

<changeSet id="201312161618-TRUNK-4129" author="rkorytkowski">
<preConditions onFail="MARK_RAN">
<not><foreignKeyConstraintExists foreignKeyName="drug_order_quantity_units"/></not>
</preConditions>
<comment>Adding quantity_units column to drug_order table</comment>
<addColumn tableName="drug_order">
<column name="quantity_units" type="int" value="NULL"/>
</addColumn>
<addForeignKeyConstraint baseTableName="drug_order" baseColumnNames="quantity_units"
constraintName="drug_order_quantity_units"
referencedTableName="concept"
referencedColumnNames="concept_id"/>
</changeSet>

<changeSet id="201312161713-TRUNK-4129" author="rkorytkowski">
<comment>Changing quantity column of drug_order to double</comment>
<modifyDataType tableName="drug_order" columnName="quantity" newDataType="double"/>
</changeSet>

<changeSet id="201312191209-TRUNK-4129" author="rkorytkowski">
<preConditions onFail="MARK_RAN">
<not>
<sqlCheck expectedResult="0">
select count(*) from drug_order;
</sqlCheck>
</not>
</preConditions>
<comment>Migrating drug order quantity to coded quantity units</comment>
<customChange class="org.openmrs.util.databasechange.MigrateDrugOrderQuantityToCodedQuantityUnitsChangeset" />
</changeSet>

</databaseChangeLog>
Expand Up @@ -101,7 +101,8 @@
<property name="frequency" type="java.lang.String" column="frequency" length="255"/>
<property name="asNeeded" type="boolean" column="as_needed" length="1" not-null="true"/>
<property name="asNeededCondition" type="string" column="as_needed_condition" length="255" />
<property name="quantity" type="int" column="quantity" length="11"/>
<property name="quantity" type="double" column="quantity" length="22"/>
<many-to-one name="quantityUnits" class="org.openmrs.Concept" column="quantity_units" />
<!-- bi-directional many-to-one association to Drug -->
<many-to-one name="drug" class="org.openmrs.Drug" not-null="false">
<column name="drug_inventory_id" />
Expand Down
@@ -0,0 +1,58 @@
/**
* The contents of this file are subject to the OpenMRS Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://license.openmrs.org
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/
package org.openmrs.util;

import org.hamcrest.core.Is;
import org.junit.Assert;
import org.junit.Test;
import org.openmrs.GlobalProperty;
import org.openmrs.api.AdministrationService;
import org.openmrs.api.context.Context;
import org.openmrs.api.db.DAOException;
import org.openmrs.test.BaseContextSensitiveTest;
import org.springframework.beans.factory.annotation.Autowired;

public class DatabaseUtilIntegrationTest extends BaseContextSensitiveTest {

@Autowired
AdministrationService adminService;

/**
* @verifies return concept_id for drug_order_quantity_units
* @see DatabaseUtil#getConceptIdForUnits(java.sql.Connection, String)
*/
@Test
public void getConceptIdForUnits_shouldReturnConcept_idForDrug_order_quantity_units() throws Exception {
adminService.saveGlobalProperty(new GlobalProperty(OpenmrsConstants.GP_ORDER_ENTRY_UNITS_TO_CONCEPTS_MAPPINGS,
"mg:5401,drug_order_quantity_units:5403,ounces:5402"));
Context.flushSession();

Integer conceptId = DatabaseUtil.getConceptIdForUnits(getConnection(), "drug_order_quantity_units");

Assert.assertThat(conceptId, Is.is(5403));
}

/**
* @verifies fail if units is not specified
* @see DatabaseUtil#getConceptIdForUnits(java.sql.Connection, String)
*/
@Test(expected = DAOException.class)
public void getConceptIdForUnits_shouldFailIfUnitsIsNotSpecified() throws Exception {
adminService.saveGlobalProperty(new GlobalProperty(OpenmrsConstants.GP_ORDER_ENTRY_UNITS_TO_CONCEPTS_MAPPINGS,
"mg:5401,ounces:5402"));
Context.flushSession();

DatabaseUtil.getConceptIdForUnits(getConnection(), "drug_order_quantity_units");
}
}

0 comments on commit 2e3c7cf

Please sign in to comment.