=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/AuditType.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/AuditType.java 1970-01-01 00:00:00 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/AuditType.java 2014-07-09 13:43:43 +0000 @@ -0,0 +1,49 @@ +package org.hisp.dhis.common; + +/* + * Copyright (c) 2004-2014, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @author Halvdan Hoem Grelland + */ +public enum AuditType +{ + UPDATE( "update" ), DELETE( "delete" ); + + private final String value; + + private AuditType( String value ) + { + this.value = value; + } + + public String getValue() + { + return value; + } +} === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValue.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValue.java 2014-07-07 10:38:51 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValue.java 2014-07-11 10:21:13 +0000 @@ -55,6 +55,10 @@ public static final String TRUE = "true"; public static final String FALSE = "false"; + // ------------------------------------------------------------------------- + // Persistent properties + // ------------------------------------------------------------------------- + private DataElement dataElement; private Period period; @@ -78,6 +82,16 @@ private Boolean followup; // ------------------------------------------------------------------------- + // Transient properties + // ------------------------------------------------------------------------- + + private transient boolean auditValueIsSet = false; + + private transient boolean valueIsSet = false; + + private transient String auditValue; + + // ------------------------------------------------------------------------- // Constructors // ------------------------------------------------------------------------- @@ -296,6 +310,14 @@ public void setValue( String value ) { + if( !auditValueIsSet ) + { + this.auditValue = valueIsSet ? this.auditValue : value; + auditValueIsSet = true; + } + + valueIsSet = true; + this.value = value; } @@ -348,4 +370,9 @@ { this.followup = followup; } + + public String getAuditValue() + { + return auditValue; + } } \ No newline at end of file === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValueAudit.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValueAudit.java 2014-03-18 08:10:10 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValueAudit.java 2014-07-10 15:06:47 +0000 @@ -28,42 +28,58 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import org.hisp.dhis.common.AuditType; +import org.hisp.dhis.dataelement.DataElement; +import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo; +import org.hisp.dhis.organisationunit.OrganisationUnit; +import org.hisp.dhis.period.Period; + import java.util.Date; /** * @author Quang Nguyen - * @version Mar 30, 2010 9:13:36 PM + * @author Halvdan Hoem Grelland */ public class DataValueAudit { private int id; - private DataValue dataValue; - private String value; - private String storedBy; + private String modifiedBy; private Date timestamp; - private String comment; + private DataElement dataElement; + + private Period period; + + private OrganisationUnit organisationUnit; + + private DataElementCategoryOptionCombo categoryOptionCombo; + + private AuditType auditType; // ------------------------------------------------------------------------- // Constructors // ------------------------------------------------------------------------- + public DataValueAudit() { - } - public DataValueAudit( DataValue dataValue, String value, String storedBy, Date timestamp, String comment ) + public DataValueAudit( DataValue dataValue, String value, String modifiedBy, Date timestamp, AuditType auditType ) { - this.dataValue = dataValue; + this.dataElement = dataValue.getDataElement(); + this.period = dataValue.getPeriod(); + this.organisationUnit = dataValue.getSource(); + this.categoryOptionCombo = dataValue.getCategoryOptionCombo(); + this.value = value; - this.storedBy = storedBy; + this.modifiedBy = modifiedBy; this.timestamp = timestamp; - this.comment = comment; + this.auditType = auditType; } // ------------------------------------------------------------------------- @@ -80,16 +96,6 @@ this.id = id; } - public DataValue getDataValue() - { - return dataValue; - } - - public void setDataValue( DataValue dataValue ) - { - this.dataValue = dataValue; - } - public String getValue() { return value; @@ -100,14 +106,14 @@ this.value = value; } - public String getStoredBy() + public String getModifiedBy() { - return storedBy; + return modifiedBy; } - public void setStoredBy( String storedBy ) + public void setModifiedBy( String modifiedBy ) { - this.storedBy = storedBy; + this.modifiedBy = modifiedBy; } public Date getTimestamp() @@ -115,18 +121,58 @@ return timestamp; } - public void setTimestamp( Date timeStamp ) - { - this.timestamp = timeStamp; - } - - public String getComment() - { - return comment; - } - - public void setComment( String comment ) - { - this.comment = comment; + public void setTimestamp( Date timestamp ) + { + this.timestamp = timestamp; + } + + public DataElement getDataElement() + { + return dataElement; + } + + public void setDataElement( DataElement dataElement ) + { + this.dataElement = dataElement; + } + + public Period getPeriod() + { + return period; + } + + public void setPeriod( Period period ) + { + this.period = period; + } + + public OrganisationUnit getOrganisationUnit() + { + return organisationUnit; + } + + public void setOrganisationUnit( OrganisationUnit organisationUnit ) + { + this.organisationUnit = organisationUnit; + } + + public DataElementCategoryOptionCombo getCategoryOptionCombo() + { + return categoryOptionCombo; + } + + public void setCategoryOptionCombo( DataElementCategoryOptionCombo categoryOptionCombo ) + { + this.categoryOptionCombo = categoryOptionCombo; + } + + public AuditType getAuditType() + { + return auditType; + } + + public void setAuditType( AuditType auditType ) + { + this.auditType = auditType; } } === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValueAuditService.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValueAuditService.java 2014-03-18 08:10:10 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValueAuditService.java 2014-07-08 17:16:48 +0000 @@ -28,37 +28,89 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import java.util.Collection; - import org.hisp.dhis.dataelement.DataElement; import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo; import org.hisp.dhis.organisationunit.OrganisationUnit; import org.hisp.dhis.period.Period; +import java.util.Collection; + /** * @author Quang Nguyen - * @version Mar 30, 2010 9:39:38 PM + * @author Halvdan Hoem Grelland */ public interface DataValueAuditService { String ID = DataValueAuditService.class.getName(); + /** + * Adds a DataValueAudit. + * + * @param dataValueAudit the DataValueAudit to add. + */ void addDataValueAudit( DataValueAudit dataValueAudit ); + /** + * Returns all DataValueAudits for the given DataValue. + * + * @param dataValue the DataValue to get DataValueAudits for. + * @return a collection of DataValueAudits which match the given DataValue, + * or an empty collection if there are no matches. + */ + Collection getDataValueAudits( DataValue dataValue ); + + /** + * Returns all DataValueAudits for the given DataElement, Period, + * OrganisationUnit and DataElementCategoryOptionCombo. + * + * @param dataElement the DataElement of the DataValueAudits. + * @param period the Period of the DataValueAudits. + * @param organisationUnit the OrganisationUnit of the DataValueAudits. + * @param categoryOptionCombo the DataElementCategoryOptionCombo of the DataValueAudits. + * @return a collection of DataValueAudits which matches the given DataElement, Period, + * OrganisationUnit and DataElementCategoryOptionCombo, or an empty collection if + * there are not matches. + */ + Collection getDataValueAudits( DataElement dataElement, + Period period, OrganisationUnit organisationUnit, DataElementCategoryOptionCombo categoryOptionCombo ); + + /** + * Deletes a DataValueAudit. + * + * @param dataValueAudit the DataValueAudit to be deleted. + */ void deleteDataValueAudit( DataValueAudit dataValueAudit ); - int deleteDataValueAuditByDataValue( DataValue dataValue ); - - void deleteDataValueAuditBySource( OrganisationUnit source ); - - void deleteDataValueAuditByDataElement( DataElement dataElement ); - - Collection getDataValueAuditByDataValue( DataValue dataValue ); - - Collection getAll(); - - public void deleteByPeriod( Period period ); - - public void deleteByDataElementCategoryOptionCombo( DataElementCategoryOptionCombo optionCombo ); + /** + * Deletes all DataValueAudits for the given DataElement. + * + * @param dataElement the DataElement for which the DataValueAudits should be deleted. + * @return the number of deleted DataValueAudits. + */ + int deleteDataValueAuditByDataElement( DataElement dataElement ); + + /** + * Deletes all DataValueAudits for the given Period. + * + * @param period the Period for which the DataValueAudits should be deleted. + * @return the number of deleted DataValueAudits. + */ + int deleteDataValueAuditByPeriod( Period period ); + + /** + * Deletes all DataValues for the given OrganisationUnit. + * + * @param organisationUnit the OrganisationUnit for which the DataValueAudits should be deleted. + * @return the number of deleted DataValueAudits. + */ + int deleteDataValueAuditByOrganisationUnit( OrganisationUnit organisationUnit ); + + /** + * Deletes all DataValues for the given DataElementCategoryOptionCombo. + * + * @param categoryOptionCombo the DataElementCategoryOptionCombo for which the DataValueAudits should be deleted. + * @return the number of deleted DataValueAudits. + */ + int deleteDataValueAuditByCategoryOptionCombo( DataElementCategoryOptionCombo categoryOptionCombo ); } === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValueAuditStore.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValueAuditStore.java 2014-03-18 08:10:10 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValueAuditStore.java 2014-07-09 13:43:43 +0000 @@ -28,36 +28,90 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import java.util.Collection; - import org.hisp.dhis.dataelement.DataElement; import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo; import org.hisp.dhis.organisationunit.OrganisationUnit; import org.hisp.dhis.period.Period; +import java.util.Collection; + /** * @author Quang Nguyen - * @version Mar 30, 2010 10:32:19 PM + * @author Halvdan Hoem Grelland */ public interface DataValueAuditStore { String ID = DataValueAuditStore.class.getName(); + /** + * Adds a DataValueAudit. + * + * @param dataValueAudit the DataValueAudit to add. + */ void addDataValueAudit( DataValueAudit dataValueAudit ); + /** + * Returns all DataValueAudits which match the DataElement, Period, OrganisationUnit + * and DataElementCategoryOptionCombo of the given DataValue. + * + * @param dataValue the DataValue to get DataValueAudits for. + * @return a collection of DataValueAudits which match the DataElement Period, + * OrganisationUnit and DataElementCategoryOptionCombo of the given DataValue, + * or an empty collection if no DataValueAudits match. + */ + Collection getDataValueAudits( DataValue dataValue ); + + /** + * Returns all DataValueAudits which match the given DataElement, Period, + * OrganisationUnit and DataElementCategoryOptionCombo. + * + * @param dataElement the DataElement of the DataValueAudits. + * @param period the Period of the DataValueAudits. + * @param organisationUnit the OrganisationUnit of the DataValueAudits. + * @param categoryOptionCombo the DataElementCategoryOptionCombo of the DataValueAudits. + * @return a collection of DataValueAudits which match the given DataElement, Period, + * OrganisationUnit and DataElementCategoryOptionCombo, or an empty collection + * if no DataValueAudits match. + */ + Collection getDataValueAudits( DataElement dataElement, + Period period, OrganisationUnit organisationUnit, DataElementCategoryOptionCombo categoryOptionCombo ); + + /** + * Deletes a DataValueAudit. + * + * @param dataValueAudit the DataValueAudit to delete. + */ void deleteDataValueAudit( DataValueAudit dataValueAudit ); - int deleteDataValueAuditByDataValue( DataValue dataValue ); - - void deleteDataValueAuditBySource( OrganisationUnit source ); - - void deleteDataValueAuditByDataElement( DataElement dataElement ); - - Collection getDataValueAuditByDataValue( DataValue dataValue ); - - Collection getAll(); - - int deleteByPeriod( Period period ); - - int deleteByDataElementCategoryOptionCombo( DataElementCategoryOptionCombo optionCombo ); + /** + * Deletes all DataValueAudits for the given DataElement. + * + * @param dataElement the DataElement for which the DataValueAudits should be deleted. + * @return the number of deleted DataValueAudits. + */ + int deleteDataValueAuditByDataElement( DataElement dataElement ); + + /** + * Deletes all DataValueAudits for the given Period. + * + * @param period the Period for which the DataValueAudits should be deleted. + * @return the number of deleted DataValueAudits. + */ + int deleteDataValueAuditByPeriod( Period period ); + + /** + * Deletes all DataValues for the given OrganisationUnit. + * + * @param organisationUnit the OrganisationUnit for which the DataValueAudits should be deleted. + * @return the number of deleted DataValueAudits. + */ + int deleteDataValueAuditByOrganisationUnit( OrganisationUnit organisationUnit ); + + /** + * Deletes all DataValues for the given DataElementCategoryOptionCombo. + * + * @param categoryOptionCombo the DataElementCategoryOptionCombo for which the DataValueAudits should be deleted. + * @return the number of deleted DataValueAudits. + */ + int deleteDataValueAuditByCategoryOptionCombo( DataElementCategoryOptionCombo categoryOptionCombo ); } === added file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/common/AuditTypeUserType.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/common/AuditTypeUserType.java 1970-01-01 00:00:00 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/common/AuditTypeUserType.java 2014-07-09 13:43:43 +0000 @@ -0,0 +1,42 @@ +package org.hisp.dhis.common; + +/* + * Copyright (c) 2004-2014, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import org.hisp.dhis.hibernate.EnumUserType; + +/** + * @author Halvdan Hoem Grelland + */ +public class AuditTypeUserType + extends EnumUserType +{ + public AuditTypeUserType() + { + super( AuditType.class ); + } +} === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/DataValueAuditDeletionHandler.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/DataValueAuditDeletionHandler.java 2014-07-02 16:51:32 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/DataValueAuditDeletionHandler.java 2014-07-10 15:06:47 +0000 @@ -66,24 +66,24 @@ @Override public void deleteOrganisationUnit( OrganisationUnit unit ) { - dataValueAuditService.deleteDataValueAuditBySource( unit ); + dataValueAuditService.deleteDataValueAuditByOrganisationUnit( unit ); } @Override public void deleteDataElement( DataElement dataElement ) { - dataValueAuditService.deleteDataValueAuditByDataElement( dataElement ); + dataValueAuditService.deleteDataValueAuditByDataElement( dataElement ); } @Override public void deletePeriod( Period period ) { - dataValueAuditService.deleteByPeriod( period ); + dataValueAuditService.deleteDataValueAuditByPeriod( period ); } @Override public void deleteDataElementCategoryOptionCombo( DataElementCategoryOptionCombo categoryOptionCombo) { - dataValueAuditService.deleteByDataElementCategoryOptionCombo( categoryOptionCombo ); + dataValueAuditService.deleteDataValueAuditByCategoryOptionCombo( categoryOptionCombo ); } } === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/DefaultDataValueAuditService.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/DefaultDataValueAuditService.java 2014-03-18 08:10:10 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/DefaultDataValueAuditService.java 2014-07-09 13:43:43 +0000 @@ -34,9 +34,11 @@ import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo; import org.hisp.dhis.organisationunit.OrganisationUnit; import org.hisp.dhis.period.Period; +import org.springframework.transaction.annotation.Transactional; /** * @author Quang Nguyen + * @author Halvdan Hoem Grelland */ public class DefaultDataValueAuditService implements DataValueAuditService @@ -56,48 +58,57 @@ // DataValueAuditService implementation // ------------------------------------------------------------------------- + @Override public void addDataValueAudit( DataValueAudit dataValueAudit ) { dataValueAuditStore.addDataValueAudit( dataValueAudit ); } + @Override + @Transactional public void deleteDataValueAudit( DataValueAudit dataValueAudit ) { dataValueAuditStore.deleteDataValueAudit( dataValueAudit ); } - public int deleteDataValueAuditByDataValue( DataValue dataValue ) - { - return dataValueAuditStore.deleteDataValueAuditByDataValue( dataValue ); - } - - public Collection getDataValueAuditByDataValue( DataValue dataValue ) - { - return dataValueAuditStore.getDataValueAuditByDataValue( dataValue ); - } - - public Collection getAll() - { - return dataValueAuditStore.getAll(); - } - - public void deleteDataValueAuditBySource( OrganisationUnit unit ) - { - dataValueAuditStore.deleteDataValueAuditBySource( unit ); - } - - public void deleteDataValueAuditByDataElement( DataElement dataElement ) - { - dataValueAuditStore.deleteDataValueAuditByDataElement( dataElement ); - - } - public void deleteByDataElementCategoryOptionCombo( DataElementCategoryOptionCombo optionCombo ) - { - dataValueAuditStore.deleteByDataElementCategoryOptionCombo( optionCombo ); - } - - public void deleteByPeriod( Period period ) - { - dataValueAuditStore.deleteByPeriod( period ); + @Override + public Collection getDataValueAudits( DataValue dataValue ) + { + return dataValueAuditStore.getDataValueAudits( dataValue ); + } + + @Override + public Collection getDataValueAudits( DataElement dataElement, Period period, + OrganisationUnit organisationUnit, DataElementCategoryOptionCombo categoryOptionCombo ) + { + return dataValueAuditStore.getDataValueAudits( dataElement, period, organisationUnit, categoryOptionCombo ); + } + + @Override + @Transactional + public int deleteDataValueAuditByDataElement( DataElement dataElement ) + { + return dataValueAuditStore.deleteDataValueAuditByDataElement( dataElement ); + } + + @Override + @Transactional + public int deleteDataValueAuditByPeriod( Period period ) + { + return dataValueAuditStore.deleteDataValueAuditByPeriod( period ); + } + + @Override + @Transactional + public int deleteDataValueAuditByOrganisationUnit( OrganisationUnit organisationUnit ) + { + return dataValueAuditStore.deleteDataValueAuditByOrganisationUnit( organisationUnit ); + } + + @Override + @Transactional + public int deleteDataValueAuditByCategoryOptionCombo( DataElementCategoryOptionCombo categoryOptionCombo ) + { + return dataValueAuditStore.deleteDataValueAuditByCategoryOptionCombo( categoryOptionCombo ); } } === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/DefaultDataValueService.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/DefaultDataValueService.java 2014-07-07 11:00:35 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/DefaultDataValueService.java 2014-07-11 10:21:13 +0000 @@ -38,6 +38,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.hisp.dhis.common.AuditType; import org.hisp.dhis.common.MapMap; import org.hisp.dhis.dataelement.CategoryOptionGroup; import org.hisp.dhis.dataelement.DataElement; @@ -48,10 +49,12 @@ import org.hisp.dhis.organisationunit.OrganisationUnit; import org.hisp.dhis.period.Period; import org.hisp.dhis.period.PeriodType; +import org.hisp.dhis.user.CurrentUserService; import org.springframework.transaction.annotation.Transactional; /** * @author Kristian Nordal + * @author Halvdan Hoem Grelland */ @Transactional public class DefaultDataValueService @@ -70,6 +73,20 @@ this.dataValueStore = dataValueStore; } + private DataValueAuditService dataValueAuditService; + + public void setDataValueAuditService( DataValueAuditService dataValueAuditService ) + { + this.dataValueAuditService = dataValueAuditService; + } + + private CurrentUserService currentUserService; + + public void setCurrentUserService( CurrentUserService currentUserService ) + { + this.currentUserService = currentUserService; + } + private DataElementCategoryService categoryService; public void setCategoryService( DataElementCategoryService categoryService ) @@ -130,6 +147,7 @@ return true; } + @Transactional public void updateDataValue( DataValue dataValue ) { if ( dataValue.isNullValue() || dataValueIsZeroAndInsignificant( dataValue.getValue(), dataValue.getDataElement() ) ) @@ -138,6 +156,10 @@ } else if ( dataValueIsValid( dataValue.getValue(), dataValue.getDataElement() ) == null ) { + DataValueAudit dataValueAudit = new DataValueAudit( dataValue, dataValue.getAuditValue(), + dataValue.getStoredBy(), new Date(), AuditType.UPDATE ); + + dataValueAuditService.addDataValueAudit( dataValueAudit ); dataValueStore.updateDataValue( dataValue ); } } @@ -145,6 +167,11 @@ @Transactional public void deleteDataValue( DataValue dataValue ) { + DataValueAudit dataValueAudit = new DataValueAudit( dataValue, dataValue.getAuditValue(), + currentUserService.getCurrentUsername(), new Date(), AuditType.DELETE ); + + dataValueAuditService.addDataValueAudit( dataValueAudit ); + dataValueStore.deleteDataValue( dataValue ); } === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/hibernate/HibernateDataValueAuditStore.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/hibernate/HibernateDataValueAuditStore.java 2014-03-18 08:10:10 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/hibernate/HibernateDataValueAuditStore.java 2014-07-10 15:06:47 +0000 @@ -28,12 +28,14 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import java.util.ArrayList; import java.util.Collection; import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; +import org.hibernate.criterion.Order; import org.hibernate.criterion.Restrictions; import org.hisp.dhis.dataelement.DataElement; import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo; @@ -42,10 +44,11 @@ import org.hisp.dhis.datavalue.DataValueAuditStore; import org.hisp.dhis.organisationunit.OrganisationUnit; import org.hisp.dhis.period.Period; +import org.hisp.dhis.period.PeriodStore; /** * @author Quang Nguyen - * @version Mar 30, 2010 10:42:16 PM + * @author Halvdan Hoem Grelland */ public class HibernateDataValueAuditStore implements DataValueAuditStore @@ -61,10 +64,18 @@ this.sessionFactory = sessionFactory; } + private PeriodStore periodStore; + + public void setPeriodStore( PeriodStore periodStore ) + { + this.periodStore = periodStore; + } + // ------------------------------------------------------------------------- // DataValueAuditStore implementation // ------------------------------------------------------------------------- + @Override public void addDataValueAudit( DataValueAudit dataValueAudit ) { Session session = sessionFactory.getCurrentSession(); @@ -72,6 +83,38 @@ session.save( dataValueAudit ); } + + @Override + public Collection getDataValueAudits( DataValue dataValue ) + { + return getDataValueAudits( dataValue.getDataElement(), dataValue.getPeriod(), + dataValue.getSource(), dataValue.getCategoryOptionCombo() ); + } + + @Override + public Collection getDataValueAudits( DataElement dataElement, Period period, + OrganisationUnit organisationUnit, DataElementCategoryOptionCombo categoryOptionCombo ) + { + Session session = sessionFactory.getCurrentSession(); + + Period storedPeriod = periodStore.reloadPeriod( period ); + + if( storedPeriod == null ) + { + return new ArrayList(); + } + + Criteria criteria = session.createCriteria( DataValueAudit.class ) + .add( Restrictions.eq( "dataElement", dataElement ) ) + .add( Restrictions.eq( "period", storedPeriod ) ) + .add( Restrictions.eq( "organisationUnit", organisationUnit ) ) + .add( Restrictions.eq( "categoryOptionCombo", categoryOptionCombo ) ) + .addOrder( Order.desc( "timestamp" ) ); + + return criteria.list(); + } + + @Override public void deleteDataValueAudit( DataValueAudit dataValueAudit ) { Session session = sessionFactory.getCurrentSession(); @@ -79,82 +122,45 @@ session.delete( dataValueAudit ); } - public int deleteDataValueAuditByDataValue( DataValue dataValue ) - { - Session session = sessionFactory.getCurrentSession(); - - Query query = session.createQuery( "delete DataValueAudit where dataValue = :dataValue" ); - query.setEntity( "dataValue", dataValue ); - - return query.executeUpdate(); - } - - public void deleteDataValueAuditBySource( OrganisationUnit source ) - { - for ( DataValueAudit each : getAll() ) - { - if ( each.getDataValue().getSource().equals( source ) ) - { - deleteDataValueAudit( each ); - } - } - } - - @SuppressWarnings( "unchecked" ) - public Collection getDataValueAuditByDataValue( DataValue dataValue ) - { - Session session = sessionFactory.getCurrentSession(); - - Criteria criteria = session.createCriteria( DataValueAudit.class ); - criteria.add( Restrictions.eq( "dataValue", dataValue ) ); - - return criteria.list(); - } - - @SuppressWarnings( "unchecked" ) - public Collection getAll() - { - Session session = sessionFactory.getCurrentSession(); - - Criteria criteria = session.createCriteria( DataValueAudit.class ); - - return criteria.list(); - } - - public void deleteDataValueAuditByDataElement( DataElement dataElement ) - { - for ( DataValueAudit each : getAll() ) - { - if ( each.getDataValue().getDataElement().equals( dataElement ) ) - { - deleteDataValueAudit( each ); - } - } - } - - public int deleteByPeriod( Period period ) - { - /* - Session session = sessionFactory.getCurrentSession(); - - Query query = session.createQuery( "delete DataValueAudit where period = :period" ); - query.setEntity( "period", period ); - - return query.executeUpdate(); - */ - return 0; - } - - public int deleteByDataElementCategoryOptionCombo( DataElementCategoryOptionCombo optionCombo ) - { - /* - Session session = sessionFactory.getCurrentSession(); - - Query query = session.createQuery( "delete DataValueAudit where optionCombo = :optionCombo" ); - query.setEntity( "optionCombo", optionCombo ); - - return query.executeUpdate(); - */ - return 0; + @Override + public int deleteDataValueAuditByDataElement( DataElement dataElement ) + { + Query query = sessionFactory.getCurrentSession() + .createQuery( "DELETE DataValueAudit WHERE dataElement = :dataElement" ) + .setEntity( "dataElement", dataElement ); + + return query.executeUpdate(); + } + + @Override + public int deleteDataValueAuditByPeriod( Period period ) + { + Period storedPeriod = periodStore.reloadPeriod( period ); + + Query query = sessionFactory.getCurrentSession() + .createQuery( "DELETE DataValueAudit WHERE period = :period" ) + .setEntity( "period", storedPeriod ); + + return query.executeUpdate(); + } + + @Override + public int deleteDataValueAuditByOrganisationUnit( OrganisationUnit organisationUnit ) + { + Query query = sessionFactory.getCurrentSession() + .createQuery( "DELETE DataValueAudit WHERE organisationUnit = :organisationUnit" ) + .setEntity( "organisationUnit", organisationUnit ); + + return query.executeUpdate(); + } + + @Override + public int deleteDataValueAuditByCategoryOptionCombo( DataElementCategoryOptionCombo categoryOptionCombo ) + { + Query query = sessionFactory.getCurrentSession() + .createQuery( "DELETE DataValueAudit WHERE categoryOptionCombo = :categoryOptionCombo" ) + .setEntity( "categoryOptionCombo", categoryOptionCombo ); + + return query.executeUpdate(); } } === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml' --- dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml 2014-07-06 17:12:17 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml 2014-07-11 10:21:13 +0000 @@ -251,6 +251,7 @@ + @@ -412,6 +413,8 @@ + + === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/datavalue/hibernate/DataValueAudit.hbm.xml' --- dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/datavalue/hibernate/DataValueAudit.hbm.xml 2013-12-19 18:12:57 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/datavalue/hibernate/DataValueAudit.hbm.xml 2014-07-09 13:43:43 +0000 @@ -4,27 +4,31 @@ "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> - + - - + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + === added file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/datavalue/DataValueAuditServiceTest.java' --- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/datavalue/DataValueAuditServiceTest.java 1970-01-01 00:00:00 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/datavalue/DataValueAuditServiceTest.java 2014-07-10 15:06:47 +0000 @@ -0,0 +1,365 @@ +package org.hisp.dhis.datavalue; + +/* + * Copyright (c) 2004-2014, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import org.hisp.dhis.DhisTest; +import org.hisp.dhis.common.AuditType; +import org.hisp.dhis.dataelement.DataElement; +import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo; +import org.hisp.dhis.dataelement.DataElementCategoryService; +import org.hisp.dhis.dataelement.DataElementService; +import org.hisp.dhis.organisationunit.OrganisationUnit; +import org.hisp.dhis.organisationunit.OrganisationUnitService; +import org.hisp.dhis.period.Period; +import org.hisp.dhis.period.PeriodService; +import org.junit.Test; + +import java.util.Collection; +import java.util.Date; + +import static junit.framework.Assert.assertTrue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +/** + * Created by Halvdan Hoem Grelland + */ +public class DataValueAuditServiceTest + extends DhisTest +{ + // ------------------------------------------------------------------------- + // Supporting data + // ------------------------------------------------------------------------- + + private DataElement dataElementA; + + private DataElement dataElementB; + + private DataElement dataElementC; + + private DataElement dataElementD; + + private DataElementCategoryOptionCombo optionCombo; + + private Period periodA; + + private Period periodB; + + private Period periodC; + + private Period periodD; + + private OrganisationUnit orgUnitA; + + private OrganisationUnit orgUnitB; + + private OrganisationUnit orgUnitC; + + private OrganisationUnit orgUnitD; + + private DataValue dataValueA; + + private DataValue dataValueB; + + private DataValue dataValueC; + + private DataValue dataValueD; + + // ------------------------------------------------------------------------- + // Set up/tear down + // ------------------------------------------------------------------------- + + @Override + public void setUpTest() + throws Exception + { + dataValueAuditService = (DataValueAuditService) getBean( DataValueAuditService.ID ); + + dataValueService = (DataValueService) getBean( DataValueService.ID ); + + dataElementService = (DataElementService) getBean( DataElementService.ID ); + + categoryService = (DataElementCategoryService) getBean( DataElementCategoryService.ID ); + + periodService = (PeriodService) getBean( PeriodService.ID ); + + organisationUnitService = (OrganisationUnitService) getBean( OrganisationUnitService.ID ); + + // --------------------------------------------------------------------- + // Add supporting data + // --------------------------------------------------------------------- + + dataElementA = createDataElement( 'A' ); + dataElementB = createDataElement( 'B' ); + dataElementC = createDataElement( 'C' ); + dataElementD = createDataElement( 'D' ); + + dataElementService.addDataElement( dataElementA ); + dataElementService.addDataElement( dataElementB ); + dataElementService.addDataElement( dataElementC ); + dataElementService.addDataElement( dataElementD ); + + periodA = createPeriod( getDay( 5 ), getDay( 6 ) ); + periodB = createPeriod( getDay( 6 ), getDay( 7 ) ); + periodC = createPeriod( getDay( 7 ), getDay( 8 ) ); + periodD = createPeriod( getDay( 8 ), getDay( 9 ) ); + + periodService.addPeriod( periodA ); + periodService.addPeriod( periodB ); + periodService.addPeriod( periodC ); + periodService.addPeriod( periodD ); + + orgUnitA = createOrganisationUnit( 'A' ); + orgUnitB = createOrganisationUnit( 'B' ); + orgUnitC = createOrganisationUnit( 'C' ); + orgUnitD = createOrganisationUnit( 'D' ); + + organisationUnitService.addOrganisationUnit( orgUnitA ); + organisationUnitService.addOrganisationUnit( orgUnitB ); + organisationUnitService.addOrganisationUnit( orgUnitC ); + organisationUnitService.addOrganisationUnit( orgUnitD ); + + optionCombo = categoryService.getDefaultDataElementCategoryOptionCombo(); + categoryService.addDataElementCategoryOptionCombo( optionCombo ); + + dataValueA = createDataValue( dataElementA, periodA, orgUnitA, "1", optionCombo ); + dataValueB = createDataValue( dataElementB, periodB, orgUnitB, "2", optionCombo ); + dataValueC = createDataValue( dataElementC, periodC, orgUnitC, "3", optionCombo ); + dataValueD = createDataValue( dataElementD, periodD, orgUnitD, "4", optionCombo ); + + dataValueService.addDataValue( dataValueA ); + dataValueService.addDataValue( dataValueB ); + dataValueService.addDataValue( dataValueC ); + dataValueService.addDataValue( dataValueD ); + } + + @Override + public boolean emptyDatabaseAfterTest() + { + return true; + } + + // ------------------------------------------------------------------------- + // Basic DataValueAudit + // ------------------------------------------------------------------------- + + @Test + public void testAddDataValueAudit() + { + Date now = new Date(); + + DataValueAudit dataValueAuditA = new DataValueAudit( dataValueA, dataValueA.getValue(), dataValueA.getStoredBy(), + now, AuditType.UPDATE ); + DataValueAudit dataValueAuditB = new DataValueAudit( dataValueB, dataValueB.getValue(), dataValueB.getStoredBy(), + now, AuditType.UPDATE ); + + dataValueAuditService.addDataValueAudit( dataValueAuditA ); + dataValueAuditService.addDataValueAudit( dataValueAuditB ); + + Collection audits = dataValueAuditService.getDataValueAudits( dataValueA ); + assertNotNull( audits ); + assertTrue( audits.contains( dataValueAuditA ) ); + } + + @Test + public void testDeleteDataValueAudit() + { + Date now = new Date(); + + DataValueAudit dataValueAuditA = new DataValueAudit( dataValueA, dataValueA.getValue(), dataValueA.getStoredBy(), + now, AuditType.UPDATE ); + DataValueAudit dataValueAuditB = new DataValueAudit( dataValueA, dataValueA.getValue(), dataValueA.getStoredBy(), + now, AuditType.DELETE ); + + dataValueAuditService.addDataValueAudit( dataValueAuditA ); + dataValueAuditService.addDataValueAudit( dataValueAuditB ); + + Collection audits = dataValueAuditService.getDataValueAudits( dataValueA ); + + assertEquals( 2, audits.size() ); + + dataValueAuditService.deleteDataValueAudit( dataValueAuditA ); + + audits = dataValueAuditService.getDataValueAudits( dataValueA ); + + assertNotNull( audits ); + assertEquals( 1, audits.size() ); + assertTrue( audits.contains( dataValueAuditB ) ); + } + + // ------------------------------------------------------------------------- + // DeletionHandler methods + // ------------------------------------------------------------------------- + + @Test + public void testDeleteDataValueAuditByDataElement() + { + Date now = new Date(); + + DataValueAudit dataValueAuditA = new DataValueAudit( dataValueA, dataValueA.getValue(), dataValueA.getStoredBy(), + now, AuditType.UPDATE ); + DataValueAudit dataValueAuditB = new DataValueAudit( dataValueB, dataValueB.getValue(), dataValueB.getStoredBy(), + now, AuditType.UPDATE ); + + DataValueAudit dataValueAuditC1 = new DataValueAudit( dataValueC, dataValueC.getValue(), dataValueC.getStoredBy(), + now, AuditType.UPDATE ); + DataValueAudit dataValueAuditC2 = new DataValueAudit( dataValueC, dataValueC.getValue(), dataValueC.getStoredBy(), + now, AuditType.UPDATE ); + + dataValueAuditService.addDataValueAudit( dataValueAuditA ); + dataValueAuditService.addDataValueAudit( dataValueAuditB ); + + dataValueAuditService.addDataValueAudit( dataValueAuditC1 ); + dataValueAuditService.addDataValueAudit( dataValueAuditC2 ); + + dataValueAuditService.deleteDataValueAuditByDataElement( dataValueAuditA.getDataElement() ); + + Collection audits = dataValueAuditService.getDataValueAudits( dataValueA ); + + assertTrue( audits.isEmpty() ); + + audits = dataValueAuditService.getDataValueAudits( dataValueB ); + assertTrue( audits.contains( dataValueAuditB ) ); + + dataValueAuditService.deleteDataValueAuditByDataElement( dataValueAuditC1.getDataElement() ); + + audits = dataValueAuditService.getDataValueAudits( dataValueD ); + + assertFalse( audits.contains( dataValueAuditC1 ) ); + assertFalse( audits.contains( dataValueAuditC2 ) ); + } + + @Test + public void testDeleteDataValueAuditByPeriod() + { + Date now = new Date(); + + DataValueAudit dataValueAuditA = new DataValueAudit( dataValueA, dataValueA.getValue(), dataValueA.getStoredBy(), + now, AuditType.UPDATE ); + DataValueAudit dataValueAuditB = new DataValueAudit( dataValueB, dataValueB.getValue(), dataValueB.getStoredBy(), + now, AuditType.UPDATE ); + + DataValueAudit dataValueAuditC1 = new DataValueAudit( dataValueC, dataValueC.getValue(), dataValueC.getStoredBy(), + now, AuditType.UPDATE ); + DataValueAudit dataValueAuditC2 = new DataValueAudit( dataValueC, dataValueC.getValue(), dataValueC.getStoredBy(), + now, AuditType.UPDATE ); + + dataValueAuditService.addDataValueAudit( dataValueAuditA ); + dataValueAuditService.addDataValueAudit( dataValueAuditB ); + + dataValueAuditService.addDataValueAudit( dataValueAuditC1 ); + dataValueAuditService.addDataValueAudit( dataValueAuditC2 ); + + dataValueAuditService.deleteDataValueAuditByPeriod( dataValueAuditA.getPeriod() ); + + Collection audits = dataValueAuditService.getDataValueAudits( dataValueA ); + + assertTrue( audits.isEmpty() ); + + dataValueAuditService.deleteDataValueAuditByPeriod( dataValueAuditC1.getPeriod() ); + + audits = dataValueAuditService.getDataValueAudits( dataValueB ); + + assertTrue( audits.contains( dataValueAuditB ) ); + + audits = dataValueAuditService.getDataValueAudits( dataValueC ); + + assertTrue( audits.isEmpty() ); + } + + @Test + public void testDeleteDataValueAuditByOrganisationUnit() + { + Date now = new Date(); + + DataValueAudit dataValueAuditA = new DataValueAudit( dataValueA, dataValueA.getValue(), dataValueA.getStoredBy(), + now, AuditType.UPDATE ); + DataValueAudit dataValueAuditB = new DataValueAudit( dataValueB, dataValueB.getValue(), dataValueB.getStoredBy(), + now, AuditType.UPDATE ); + + DataValueAudit dataValueAuditC1 = new DataValueAudit( dataValueC, dataValueC.getValue(), dataValueC.getStoredBy(), + now, AuditType.UPDATE ); + DataValueAudit dataValueAuditC2 = new DataValueAudit( dataValueC, dataValueC.getValue(), dataValueC.getStoredBy(), + now, AuditType.UPDATE ); + + dataValueAuditService.addDataValueAudit( dataValueAuditA ); + dataValueAuditService.addDataValueAudit( dataValueAuditB ); + + dataValueAuditService.addDataValueAudit( dataValueAuditC1 ); + dataValueAuditService.addDataValueAudit( dataValueAuditC2 ); + + dataValueAuditService.deleteDataValueAuditByOrganisationUnit( dataValueAuditA.getOrganisationUnit() ); + + Collection audits = dataValueAuditService.getDataValueAudits( dataValueA ); + + assertTrue( audits.isEmpty() ); + + dataValueAuditService.deleteDataValueAuditByOrganisationUnit( dataValueAuditC1.getOrganisationUnit() ); + + audits = dataValueAuditService.getDataValueAudits( dataValueC ); + + assertTrue( audits.isEmpty() ); + + audits = dataValueAuditService.getDataValueAudits( dataValueB ); + + assertNotNull( dataValueAuditB ); + assertNotNull( audits ); + + assertTrue( audits.contains( dataValueAuditB ) ); + } + + @Test + public void testDeleteDataValueAuditByCategoryOptionCombo() + { + Date now = new Date(); + + DataValueAudit dataValueAuditA = new DataValueAudit( dataValueA, dataValueA.getValue(), dataValueA.getStoredBy(), + now, AuditType.UPDATE ); + DataValueAudit dataValueAuditB = new DataValueAudit( dataValueB, dataValueB.getValue(), dataValueB.getStoredBy(), + now, AuditType.UPDATE ); + DataValueAudit dataValueAuditC = new DataValueAudit( dataValueC, dataValueC.getValue(), dataValueC.getStoredBy(), + now, AuditType.UPDATE ); + + dataValueAuditService.addDataValueAudit( dataValueAuditA ); + dataValueAuditService.addDataValueAudit( dataValueAuditB ); + dataValueAuditService.addDataValueAudit( dataValueAuditC ); + + dataValueAuditService.deleteDataValueAuditByCategoryOptionCombo( optionCombo ); + + Collection audits = dataValueAuditService.getDataValueAudits( dataValueA ); + assertTrue( audits.isEmpty() ); + + audits = dataValueAuditService.getDataValueAudits( dataValueB ); + assertTrue( audits.isEmpty() ); + + audits = dataValueAuditService.getDataValueAudits( dataValueC ); + assertTrue( audits.isEmpty() ); + } +} === modified file 'dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/dbms/HibernateDbmsManager.java' --- dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/dbms/HibernateDbmsManager.java 2014-04-27 21:52:33 +0000 +++ dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/dbms/HibernateDbmsManager.java 2014-07-08 17:16:48 +0000 @@ -82,6 +82,7 @@ emptyTable( "sqlview" ); emptyTable( "datavalue_audit" ); + emptyTable( "datavalueaudit" ); emptyTable( "datavalue" ); emptyTable( "completedatasetregistration" ); === modified file 'dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/DhisConvenienceTest.java' --- dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/DhisConvenienceTest.java 2014-06-30 18:27:25 +0000 +++ dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/DhisConvenienceTest.java 2014-07-08 17:16:48 +0000 @@ -79,6 +79,7 @@ import org.hisp.dhis.dataset.DataSetService; import org.hisp.dhis.dataset.SectionService; import org.hisp.dhis.datavalue.DataValue; +import org.hisp.dhis.datavalue.DataValueAuditService; import org.hisp.dhis.datavalue.DataValueService; import org.hisp.dhis.expression.Expression; import org.hisp.dhis.expression.ExpressionService; @@ -198,6 +199,8 @@ protected DataValueService dataValueService; + protected DataValueAuditService dataValueAuditService; + protected ResourceTableService resourceTableService; protected MappingService mappingService; === modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/GetHistoryAction.java' --- dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/GetHistoryAction.java 2014-05-22 12:40:24 +0000 +++ dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/GetHistoryAction.java 2014-07-10 15:06:47 +0000 @@ -55,6 +55,7 @@ /** * @author Torgeir Lorange Ostby + * @author Halvdan Hoem Grelland */ public class GetHistoryAction implements Action @@ -257,7 +258,9 @@ OrganisationUnit organisationUnit = organisationUnitService.getOrganisationUnit( organisationUnitId ); DataElementCategoryOptionCombo attributeOptionCombo = inputUtils.getAttributeOptionCombo( ServletActionContext.getResponse(), cc, cp ); - + + dataValueAudits = dataValueAuditService.getDataValueAudits( dataElement, period, organisationUnit, categoryOptionCombo ); + dataValue = dataValueService.getDataValue( dataElement, period, organisationUnit, categoryOptionCombo, attributeOptionCombo ); if ( dataValue != null ) @@ -272,8 +275,6 @@ minMaxInvalid = !DataElement.VALUE_TYPE_INT.equals( dataElement.getType() ); - dataValueAudits = dataValueAuditService.getDataValueAuditByDataValue( dataValue ); - commentOptionSet = dataElement.getCommentOptionSet(); return SUCCESS; === modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/org/hisp/dhis/de/i18n_module.properties' --- dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/org/hisp/dhis/de/i18n_module.properties 2014-06-27 16:27:09 +0000 +++ dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/org/hisp/dhis/de/i18n_module.properties 2014-07-10 15:06:47 +0000 @@ -8,6 +8,8 @@ stored_by=Stored by stored_date=Stored date last_updated=Last updated +update=Update +delete=Delete no_value=No value maximum=Maximum organisation_unit=Organisation Unit @@ -34,6 +36,7 @@ min_limit=Min limit max_limit=Max limit dataelement_history=Data element history +audit_trail=Audit trail nr=Nr min_max_limits=Min-max limits run_validation=Run validation @@ -78,6 +81,8 @@ select_period=Select period select_option=Select option change_from=change from +modification=Modification +modified_by=Modified by to=to on=On value=Value @@ -113,4 +118,5 @@ section=Section print_form=Print form print_blank_form=Print blank form -instruction=Instruction \ No newline at end of file +instruction=Instruction +there_is_no_audit_trail_for_this_value=There is no audit trail for this value === modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/history.vm' --- dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/history.vm 2014-06-27 16:27:09 +0000 +++ dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/history.vm 2014-07-10 15:06:47 +0000 @@ -4,6 +4,10 @@ $( document ).ready( function() { dhis2.de.insertCommentOptionSet( '$!{commentOptionSet.uid}' ); + + $( function() { + $("#historyTabs").tabs(); + }); } ); @@ -75,32 +79,65 @@ - - - - - #if( $historyInvalid ) -
$encoder.htmlEncode( $i18n.getString( "history_not_valid" ) )
- #else -
$encoder.htmlEncode( $i18n.getString( "dataelement_history" ) )
- - #end - - - #if( $dataValueAuditSize > 0 ) - - - - <
>$encoder.htmlEncode( $i18n.getString( "datavalue_history" ) )
- #foreach( $eachDataValueAudit in $dataValueAudits ) -

- $encoder.htmlEncode( $i18n.getString( "on" ) ) $eachDataValueAudit.timeStamp, - $eachDataValueAudit.storedBy - $encoder.htmlEncode( $i18n.getString( "change_from" ) ) $eachDataValueAudit.value -

- #end - - - #end - + + + +
+ +
+ #if( $historyInvalid ) + $encoder.htmlEncode( $i18n.getString( "history_not_valid" ) ) + #else + + #end +
+
+ #if( $dataValueAuditSize > 0 ) + + + + + + + + + + + #foreach( $dataValueAudit in $dataValueAudits ) + + + + + + + #end + +
$encoder.htmlEncode( $i18n.getString( "on" ) )$encoder.htmlEncode( $i18n.getString( "modified_by" ) )$encoder.htmlEncode( $i18n.getString( "value" ) )$encoder.htmlEncode( $i18n.getString( "modification" ) )
+ $format.formatDateTime( $dataValueAudit.timestamp ) + + #if( $dataValueAudit.modifiedBy ) + $dataValueAudit.modifiedBy + #else + $encoder.htmlEncode( $i18n.getString( "no_value" ) ) + #end + + #if( $dataValueAudit.value ) + $dataValueAudit.value + #else + $encoder.htmlEncode( $i18n.getString( "no_value" ) ) + #end + + $i18n.getString( $dataValueAudit.auditType.getValue() ) +
+ #else + $encoder.htmlEncode( $i18n.getString( "there_is_no_audit_trail_for_this_value" ) ) + #end +
+
+ + + \ No newline at end of file === modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/style/dhis-web-dataentry.css' --- dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/style/dhis-web-dataentry.css 2014-07-08 14:52:55 +0000 +++ dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/style/dhis-web-dataentry.css 2014-07-10 15:06:47 +0000 @@ -57,7 +57,7 @@ padding-right: 50px; } -.hidden +.hidden { display: none; } @@ -103,7 +103,7 @@ .sectionFilter { padding: 5px; - border: solid 1px #f0f0f0; + border: solid 1px #f0f0f0; outline: 0; color: #333; height: 14px; @@ -135,3 +135,91 @@ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.06); } +/* jQuery UI tab style overrides for data value history view */ + +#historyTabs +{ + padding: 0; + width: 545px; + height: 345px; +} + +#historyTabs.ui-tabs.ui-widget.ui-widget-content +{ + border-width: 0; +} + +#historyTabs .ui-tabs-nav +{ + border-width: 0px; + border-bottom-width: 1px; + border-bottom-color: inherit; + border-radius: 0; + background: transparent; + padding: 0; +} + +#historyTabs.ui-widget-content +{ + background: none; +} + +#historyTabs .ui-tabs-panel. ui-widget-content +{ + padding-top: 0.5em; + padding-left: 0.5em; + padding-right: 0.5em; + border-width: 0; +} + +/* History audit table */ + +#historyAuditTable +{ + width: 100%; + border-collapse: collapse; + text-align: left; + background-color: #F5F5F5; +} + +#historyAuditTable tbody tr:nth-child( odd ) +{ + background-color: #EDEDED; +} + +#historyAuditTable td, #historyAuditTable th +{ + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; +} + +#historyAuditTable td +{ + border: 1px solid lightgrey; +} + +#historyAuditTable th +{ + background-color: #DFEFFC; + border: 1px solid #C5DBEC; +} + +#historyTabs-chart +{ + padding-bottom: 0; + padding-left: 0; +} + +#historyTabs-audit +{ + height: 260px; + overflow: auto; + padding-top: 0; + margin-top: 20px; +} + +#historyTabs table thead th .text +{ + position: absolute; +}