← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 14954: TEI query, filtering on event status

 

------------------------------------------------------------
revno: 14954
committer: Lars Helge Øverland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Wed 2014-04-23 22:15:31 +0200
message:
  TEI query, filtering on event status
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/event/EventStatus.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityInstanceService.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityInstanceStore.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/JdbcEventStore.java
  dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/DefaultTrackedEntityInstanceService.java
  dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/hibernate/HibernateTrackedEntityInstanceStore.java


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/event/EventStatus.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/event/EventStatus.java	2014-04-22 23:37:46 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/event/EventStatus.java	2014-04-23 20:15:31 +0000
@@ -71,7 +71,7 @@
             return false;
         }
         
-        return ACTIVE.equals( status ) || COMPLETED.equals( status ) || VISITED.equals( status );
+        return COMPLETED.equals( status ) || VISITED.equals( status );
     }
 }
 

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityInstanceService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityInstanceService.java	2014-04-22 23:37:46 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityInstanceService.java	2014-04-23 20:15:31 +0000
@@ -380,4 +380,47 @@
      */
     Collection<TrackedEntityInstance> getTrackedEntityInstancesByAttributeValue( String searchText, int attributeId,
         Integer min, Integer max );
+
+    /**
+     * Search entityInstances by attribute values and/or a program which
+     * entityInstances enrolled into
+     * 
+     * @param searchKeys The key for searching entityInstances by attribute
+     *        values, identifiers and/or a program
+     * @param orgunit Organisation unit where entityInstances registered
+     * @param followup Only getting entityInstances with program risked if this
+     *        property is true. And getting entityInstances without program
+     *        risked if its value is false
+     * @param attributes The attribute values of these attribute are displayed
+     *        into result
+     * @param statusEnrollment The status of program of entityInstances. There
+     *        are three status, includes Active enrollments only, Completed
+     *        enrollments only and Active and completed enrollments
+     * @param min
+     * @param max
+     * 
+     * @return An object
+     */
+    Collection<TrackedEntityInstance> searchTrackedEntityInstances( List<String> searchKeys,
+        Collection<OrganisationUnit> orgunit, Boolean followup, Collection<TrackedEntityAttribute> attributes,
+        Integer statusEnrollment, Integer min, Integer max );
+
+    /**
+     * Get the number of entityInstances who meet the criteria for searching
+     * 
+     * @param searchKeys The key for searching entityInstances by attribute
+     *        values and/or a program
+     * @param orgunit Organisation unit where entityInstances registered
+     * @param followup Only getting entityInstances with program risked if this
+     *        property is true. And getting entityInstances without program
+     *        risked if its value is false
+     * @param statusEnrollment The status of program of entityInstances. There
+     *        are three status, includes Active enrollments only, Completed
+     *        enrollments only and Active and completed enrollments
+     * 
+     * @return The number of entityInstances
+     */
+    int countSearchTrackedEntityInstances( List<String> searchKeys, Collection<OrganisationUnit> orgunit,
+        Boolean followup, Integer statusEnrollment );
+
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityInstanceStore.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityInstanceStore.java	2014-04-22 23:37:46 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityInstanceStore.java	2014-04-23 20:15:31 +0000
@@ -50,9 +50,9 @@
     final int MAX_RESULTS = 50000;
 
     List<Map<String, String>> getTrackedEntityInstances( TrackedEntityInstanceQueryParams params );
-    
+
     int getTrackedEntityInstanceCount( TrackedEntityInstanceQueryParams params );
-    
+
     /**
      * Search entityInstances who registered in a certain organisation unit
      * 
@@ -125,7 +125,7 @@
      * @return List of instances
      */
     Collection<TrackedEntityInstance> getByPhoneNumber( String phoneNumber, Integer min, Integer max );
-    
+
     /**
      * Search events which meet the criteria for searching
      * 
@@ -161,17 +161,17 @@
     Collection<TrackedEntityInstance> getByProgram( Program program, Integer min, Integer max );
 
     /**
-     * Validate entity-instances attribute values and validation criteria by program
-     * before registering / updating information
+     * Validate entity-instances attribute values and validation criteria by
+     * program before registering / updating information
      * 
      * @param entityinstance TrackedEntityInstance object
      * @param program Program which person needs to enroll. If this parameter is
      *        null, the system check attribute values of the instances
      * @param format I18nFormat
      * 
-     * @return Error code 0 : Validation is OK 
-     *                    1_<duplicate-value> : The attribute value is duplicated 
-     *                    2_<validation-criteria-id> : Violate validation criteria of the program
+     * @return Error code 0 : Validation is OK 1_<duplicate-value> : The
+     *         attribute value is duplicated 2_<validation-criteria-id> :
+     *         Violate validation criteria of the program
      */
     String validate( TrackedEntityInstance entityinstance, Program program, I18nFormat format );
 
@@ -185,7 +185,7 @@
      * 
      * @return ValidationCriteria object which is violated
      */
-    ValidationCriteria validateEnrollment(TrackedEntityInstance entityinstance, Program program, I18nFormat format );
+    ValidationCriteria validateEnrollment( TrackedEntityInstance entityinstance, Program program, I18nFormat format );
 
     /**
      * Validate instances attribute values and validation criteria by program
@@ -197,4 +197,46 @@
      * @return TrackedEntityInstance list
      */
     Collection<TrackedEntityInstance> getByAttributeValue( String searchText, int attributeId, Integer min, Integer max );
+
+    /**
+     * Search entityInstances by attribute values and/or a program which
+     * entityInstances enrolled into
+     * 
+     * @param searchKeys The key for searching entityInstances by attribute
+     *        values, identifiers and/or a program
+     * @param orgunit Organisation unit where entityInstances registered
+     * @param followup Only getting entityInstances with program risked if this
+     *        property is true. And getting entityInstances without program
+     *        risked if its value is false
+     * @param attributes The attribute values of these attribute are displayed
+     *        into result
+     * @param statusEnrollment The status of program of entityInstances. There
+     *        are three status, includes Active enrollments only, Completed
+     *        enrollments only and Active and completed enrollments
+     * @param min
+     * @param max
+     * 
+     * @return An object
+     */
+    Collection<TrackedEntityInstance> search( List<String> searchKeys, Collection<OrganisationUnit> orgunits,
+        Boolean followup, Collection<TrackedEntityAttribute> attributes, Integer statusEnrollment, Integer min,
+        Integer max );
+
+    /**
+     * Get the number of entityInstances who meet the criteria for searching
+     * 
+     * @param searchKeys The key for searching entityInstances by attribute
+     *        values and/or a program
+     * @param orgunit Organisation unit where entityInstances registered
+     * @param followup Only getting entityInstances with program risked if this
+     *        property is true. And getting entityInstances without program
+     *        risked if its value is false
+     * @param statusEnrollment The status of program of entityInstances. There
+     *        are three status, includes Active enrollments only, Completed
+     *        enrollments only and Active and completed enrollments
+     * 
+     * @return The number of entityInstances
+     */
+    int countSearch( List<String> searchKeys, Collection<OrganisationUnit> orgunits, Boolean followup,
+        Integer statusEnrollment );
 }

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/JdbcEventStore.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/JdbcEventStore.java	2014-04-22 23:37:46 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/JdbcEventStore.java	2014-04-23 20:15:31 +0000
@@ -119,8 +119,9 @@
                 event.setProgramStage( rowSet.getString( "ps_uid" ) );
                 event.setStoredBy( rowSet.getString( "psi_completeduser" ) );
                 event.setOrgUnit( rowSet.getString( "ou_uid" ) );
-                event.setEventDate( StringUtils.defaultIfEmpty( rowSet.getString( "psi_executiondate" ), rowSet.getString( "psi_duedate" ) ) );
-                
+                event.setEventDate( StringUtils.defaultIfEmpty( 
+                    rowSet.getString( "psi_executiondate" ), rowSet.getString( "psi_duedate" ) ) );
+
                 if ( rowSet.getBoolean( "ps_capturecoordinates" ) )
                 {
                     Double longitude = rowSet.getDouble( "psi_longitude" );
@@ -177,7 +178,7 @@
         SqlHelper hlp = new SqlHelper();
 
         String sql = 
-            "select p.uid as p_uid, ps.uid as ps_uid, ps.capturecoordinates as ps_capturecoordinates, pa.uid as pa_uid, psi.uid as psi_uid, psi.status as psi_status, ou.uid as ou_uid, " +
+            "select p.uid as p_uid, ps.uid as ps_uid, ps.capturecoordinates as ps_capturecoordinates, pa.uid as pa_uid, psi.uid as psi_uid, psi.status as psi_status, ou.uid as ou_uid, " + 
             "psi.executiondate as psi_executiondate, psi.duedate as psi_duedate, psi.completeduser as psi_completeduser, psi.longitude as psi_longitude, psi.latitude as psi_latitude, " +
             "pdv.value as pdv_value, pdv.storedby as pdv_storedby, pdv.providedelsewhere as pdv_providedelsewhere, de.uid as de_uid " +
             "from program p " +
@@ -226,24 +227,60 @@
             sql += hlp.whereAnd() + " pi.followup is " + (followUp ? "true" : "false") + " ";
         }
 
-        if ( orgUnitIds != null && !orgUnitIds.isEmpty() )
-        {
-            sql += hlp.whereAnd() + " ou.organisationunitid in (" + getCommaDelimitedString( orgUnitIds ) + ") ";
-        }
-
-        if ( startDate != null )
-        {
-            sql += hlp.whereAnd() + " psi.executiondate >= '" + getMediumDateString( startDate ) + "' ";
-        }
-
-        if ( endDate != null )
-        {
-            sql += hlp.whereAnd() + " psi.executiondate <= '" + getMediumDateString( endDate ) + "' ";
-        }
-
-        if ( status != null )
-        {
-            sql += hlp.whereAnd() + " psi.status = " + status.getValue() + " ";
+        if ( status == null || EventStatus.isExistingEvent( status ) )
+        {
+            if ( orgUnitIds != null && !orgUnitIds.isEmpty() )
+            {
+                sql += hlp.whereAnd() + " psi.organisationunitid in (" + getCommaDelimitedString( orgUnitIds ) + ") ";
+            }
+
+            if ( startDate != null )
+            {
+                sql += hlp.whereAnd() + " psi.executiondate >= '" + getMediumDateString( startDate ) + "' ";
+            }
+
+            if ( endDate != null )
+            {
+                sql += hlp.whereAnd() + " psi.executiondate <= '" + getMediumDateString( endDate ) + "' ";
+            }
+        }
+        else
+        {
+            if ( orgUnitIds != null && !orgUnitIds.isEmpty() )
+            {
+                sql += hlp.whereAnd() + " tei.organisationunitid in (" + getCommaDelimitedString( orgUnitIds ) + ") ";
+            }
+
+            if ( startDate != null )
+            {
+                sql += hlp.whereAnd() + " psi.duedate >= '" + getMediumDateString( startDate ) + "' ";
+            }
+
+            if ( endDate != null )
+            {
+                sql += hlp.whereAnd() + " psi.duedate <= '" + getMediumDateString( endDate ) + "' ";
+            }
+            
+            if ( status == EventStatus.VISITED )
+            {
+                sql = "and psi.completed = false and psi.status = 0 ";
+            }
+            else if ( status == EventStatus.COMPLETED )
+            {
+                sql = "and psi.completed = true and psi.status = 0 ";
+            }
+            else if ( status == EventStatus.FUTURE_VISIT )
+            {
+                sql += "and psi.executiondate is null and date(now()) <= date(psi.duedate) and psi.status = 0 ";
+            }
+            else  if ( status == EventStatus.LATE_VISIT )
+            {
+                sql += "and psi.executiondate is null and date(now()) > date(psi.duedate) and psi.status = 0 ";
+            }
+            else
+            {
+                sql += "and psi.status = " + status.getValue() + " ";
+            }
         }
 
         sql += " order by psi_uid;";

=== modified file 'dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/DefaultTrackedEntityInstanceService.java'
--- dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/DefaultTrackedEntityInstanceService.java	2014-04-22 23:37:46 +0000
+++ dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/DefaultTrackedEntityInstanceService.java	2014-04-23 20:15:31 +0000
@@ -81,7 +81,7 @@
     implements TrackedEntityInstanceService
 {
     private static final Log log = LogFactory.getLog( DefaultTrackedEntityInstanceService.class );
-    
+
     // -------------------------------------------------------------------------
     // Dependencies
     // -------------------------------------------------------------------------
@@ -106,7 +106,7 @@
     {
         this.attributeService = attributeService;
     }
-    
+
     private TrackedEntityService trackedEntityService;
 
     public void setTrackedEntityService( TrackedEntityService trackedEntityService )
@@ -127,27 +127,27 @@
     {
         this.relationshipTypeService = relationshipTypeService;
     }
-    
+
     private ProgramService programService;
 
     public void setProgramService( ProgramService programService )
     {
         this.programService = programService;
     }
-    
+
     private OrganisationUnitService organisationUnitService;
 
     public void setOrganisationUnitService( OrganisationUnitService organisationUnitService )
     {
         this.organisationUnitService = organisationUnitService;
     }
-        
+
     // -------------------------------------------------------------------------
     // Implementation methods
     // -------------------------------------------------------------------------
-    
-    //TODO lower index on attribute value?
-    
+
+    // TODO lower index on attribute value?
+
     @Override
     public Grid getTrackedEntityInstances( TrackedEntityInstanceQueryParams params )
     {
@@ -164,10 +164,10 @@
                 organisationUnit.setLevel( organisationUnitService.getLevelOfOrganisationUnit( organisationUnit.getId() ) );
             }
         }
-        
+
         // ---------------------------------------------------------------------
         // If params of type query and no attributes or filters defined, use
-        // attributes from program if exists, if not, use display-in-list 
+        // attributes from program if exists, if not, use display-in-list
         // attributes.
         // ---------------------------------------------------------------------
 
@@ -177,12 +177,12 @@
             {
                 params.addAttributesIfNotExist( QueryItem.getQueryItems( params.getProgram().getTrackedEntityAttributes() ) );
             }
-            else 
+            else
             {
                 Collection<TrackedEntityAttribute> filters = attributeService.getAllTrackedEntityAttributes();
                 Collection<TrackedEntityAttribute> attributes = attributeService.getTrackedEntityAttributesDisplayInList( true );
                 filters.removeAll( attributes );
-                
+
                 params.addAttributesIfNotExist( QueryItem.getQueryItems( attributes ) );
                 params.addFiltersIfNotExist( QueryItem.getQueryItems( filters ) );
             }
@@ -205,12 +205,12 @@
         grid.addHeader( new GridHeader( LAST_UPDATED_ID, "Last updated" ) );
         grid.addHeader( new GridHeader( ORG_UNIT_ID, "Org unit" ) );
         grid.addHeader( new GridHeader( TRACKED_ENTITY_ID, "Tracked entity" ) );
-        
+
         for ( QueryItem item : params.getAttributes() )
         {
             grid.addHeader( new GridHeader( item.getItem().getUid(), item.getItem().getName() ) );
         }
-        
+
         List<Map<String, String>> entities = trackedEntityInstanceStore.getTrackedEntityInstances( params );
 
         // ---------------------------------------------------------------------
@@ -218,49 +218,49 @@
         // ---------------------------------------------------------------------
 
         Set<String> tes = new HashSet<String>();
-                
+
         for ( Map<String, String> entity : entities )
-        {            
+        {
             grid.addRow();
             grid.addValue( entity.get( TRACKED_ENTITY_INSTANCE_ID ) );
             grid.addValue( entity.get( CREATED_ID ) );
             grid.addValue( entity.get( LAST_UPDATED_ID ) );
             grid.addValue( entity.get( ORG_UNIT_ID ) );
             grid.addValue( entity.get( TRACKED_ENTITY_ID ) );
-            
+
             tes.add( entity.get( TRACKED_ENTITY_ID ) );
-            
+
             for ( QueryItem item : params.getAttributes() )
             {
                 grid.addValue( entity.get( item.getItemId() ) );
             }
         }
 
-        Map<Object, Object> metaData = new HashMap<Object, Object>();   
+        Map<Object, Object> metaData = new HashMap<Object, Object>();
 
         if ( params.isPaging() )
         {
             int count = trackedEntityInstanceStore.getTrackedEntityInstanceCount( params );
-            
+
             Pager pager = new Pager( params.getPageWithDefault(), count, params.getPageSizeWithDefault() );
             metaData.put( PAGER_META_KEY, pager );
         }
-        
+
         if ( !params.isSkipMeta() )
-        {         
+        {
             Map<String, String> names = new HashMap<String, String>();
-            
+
             for ( String te : tes )
             {
                 TrackedEntity entity = trackedEntityService.getTrackedEntity( te );
                 names.put( te, entity != null ? entity.getDisplayName() : null );
             }
-            
+
             metaData.put( META_DATA_NAMES_KEY, names );
         }
 
         grid.setMetaData( metaData );
-        
+
         return grid;
     }
 
@@ -269,7 +269,7 @@
         throws IllegalQueryException
     {
         String violation = null;
-        
+
         if ( params == null )
         {
             throw new IllegalQueryException( "Params cannot be null" );
@@ -279,64 +279,65 @@
         {
             violation = "At least one organisation unit must be specified";
         }
-        
+
         if ( params.hasProgram() && params.hasTrackedEntity() )
         {
             violation = "Program and tracked entity cannot be specified simultaneously";
         }
-        
+
         if ( params.hasProgramStatus() && !params.hasProgram() )
         {
             violation = "Program must be defined when program status is defined";
         }
-        
+
         if ( params.hasFollowUp() && !params.hasProgram() )
         {
             violation = "Program must be defined when follow up status is defined";
         }
-        
+
         if ( params.hasProgramStartDate() && !params.hasProgram() )
         {
             violation = "Program must be defined when program start date is specified";
         }
-        
+
         if ( params.hasProgramEndDate() && !params.hasProgram() )
         {
             violation = "Program must be defined when program end date is specified";
         }
 
-        if ( params.hasEventStatus() && ( !params.hasEventStartDate() || !params.hasEventEndDate() ) )
+        if ( params.hasEventStatus() && (!params.hasEventStartDate() || !params.hasEventEndDate()) )
         {
             violation = "Event start and end date must be specified when event status is specified";
         }
-        
+
         if ( params.isOrQuery() && params.hasFilters() )
         {
             violation = "Query cannot be specified together with filters";
         }
-        
+
         if ( !params.getDuplicateAttributes().isEmpty() )
         {
             violation = "Attributes cannot be specified more than once: " + params.getDuplicateAttributes();
         }
-        
+
         if ( !params.getDuplicateFilters().isEmpty() )
         {
             violation = "Filters cannot be specified more than once: " + params.getDuplicateFilters();
         }
-                
+
         if ( violation != null )
         {
             log.warn( "Validation failed: " + violation );
-            
+
             throw new IllegalQueryException( violation );
         }
     }
-    
+
     @Override
-    public TrackedEntityInstanceQueryParams getFromUrl( String query, Set<String> attribute, Set<String> filter, Set<String> ou, 
-        OrganisationUnitSelectionMode ouMode, String program, ProgramStatus programStatus, Boolean followUp, Date programStartDate, Date programEndDate,
-        String trackedEntity, EventStatus eventStatus, Date eventStartDate, Date eventEndDate, boolean skipMeta, Integer page, Integer pageSize )
+    public TrackedEntityInstanceQueryParams getFromUrl( String query, Set<String> attribute, Set<String> filter,
+        Set<String> ou, OrganisationUnitSelectionMode ouMode, String program, ProgramStatus programStatus,
+        Boolean followUp, Date programStartDate, Date programEndDate, String trackedEntity, EventStatus eventStatus,
+        Date eventStartDate, Date eventEndDate, boolean skipMeta, Integer page, Integer pageSize )
     {
         TrackedEntityInstanceQueryParams params = new TrackedEntityInstanceQueryParams();
 
@@ -345,17 +346,17 @@
             for ( String attr : attribute )
             {
                 QueryItem it = getQueryItem( attr );
-                
+
                 params.getAttributes().add( it );
             }
         }
-        
+
         if ( filter != null )
         {
             for ( String filt : filter )
             {
                 QueryItem it = getQueryItem( filt );
-                
+
                 params.getFilters().add( it );
             }
         }
@@ -365,25 +366,25 @@
             for ( String orgUnit : ou )
             {
                 OrganisationUnit organisationUnit = organisationUnitService.getOrganisationUnit( orgUnit );
-                
+
                 if ( organisationUnit == null )
                 {
                     throw new IllegalQueryException( "Organisation unit does not exist: " + orgUnit );
                 }
-                
+
                 params.getOrganisationUnits().add( organisationUnit );
             }
         }
-        
+
         Program pr = program != null ? programService.getProgram( program ) : null;
-        
+
         if ( program != null && pr == null )
         {
             throw new IllegalQueryException( "Program does not exist: " + program );
         }
-                
+
         TrackedEntity te = trackedEntity != null ? trackedEntityService.getTrackedEntity( trackedEntity ) : null;
-        
+
         if ( trackedEntity != null && te == null )
         {
             throw new IllegalQueryException( "Tracked entity does not exist: " + program );
@@ -403,10 +404,10 @@
         params.setSkipMeta( skipMeta );
         params.setPage( page );
         params.setPageSize( pageSize );
-        
+
         return params;
     }
-    
+
     private QueryItem getQueryItem( String item )
     {
         if ( !item.contains( DimensionalObjectUtils.DIMENSION_NAME_SEP ) )
@@ -434,7 +435,7 @@
         {
             throw new IllegalQueryException( "Attribute does not exist: " + item );
         }
-        
+
         if ( operator != null && filter != null )
         {
             return new QueryItem( at, operator, filter, at.isNumericType() );
@@ -442,9 +443,9 @@
         else
         {
             return new QueryItem( at, at.isNumericType() );
-        }        
+        }
     }
-    
+
     @Override
     public int addTrackedEntityInstance( TrackedEntityInstance instance )
     {
@@ -739,8 +740,8 @@
     public List<Integer> getProgramStageInstances( List<String> searchKeys, Collection<OrganisationUnit> orgunits,
         Boolean followup, Integer statusEnrollment, Integer min, Integer max )
     {
-        return trackedEntityInstanceStore.getProgramStageInstances( searchKeys, orgunits, followup, null, statusEnrollment,
-            min, max );
+        return trackedEntityInstanceStore.getProgramStageInstances( searchKeys, orgunits, followup, null,
+            statusEnrollment, min, max );
     }
 
     @Override
@@ -763,11 +764,13 @@
     }
 
     @Override
-    public Collection<TrackedEntityInstance> searchTrackedEntityInstancesForMobile( String searchText, int orgUnitId, int attributeId )
+    public Collection<TrackedEntityInstance> searchTrackedEntityInstancesForMobile( String searchText, int orgUnitId,
+        int attributeId )
     {
         Set<TrackedEntityInstance> entityInstances = new HashSet<TrackedEntityInstance>();
 
-        entityInstances.addAll( getTrackedEntityInstancesByAttributeValue( searchText, attributeId, 0, Integer.MAX_VALUE ) );
+        entityInstances.addAll( getTrackedEntityInstancesByAttributeValue( searchText, attributeId, 0,
+            Integer.MAX_VALUE ) );
 
         if ( orgUnitId != 0 )
         {
@@ -783,7 +786,7 @@
             }
             entityInstances.removeAll( toRemoveList );
         }
-        
+
         return entityInstances;
     }
 
@@ -794,4 +797,20 @@
         return trackedEntityInstanceStore.getByAttributeValue( searchText, attributeId, min, max );
     }
 
+    @Override
+    public Collection<TrackedEntityInstance> searchTrackedEntityInstances( List<String> searchKeys,
+        Collection<OrganisationUnit> orgunits, Boolean followup, Collection<TrackedEntityAttribute> attributes,
+        Integer statusEnrollment, Integer min, Integer max )
+    {
+        return trackedEntityInstanceStore.search( searchKeys, orgunits, followup, attributes, statusEnrollment, min,
+            max );
+    }
+
+    @Override
+    public int countSearchTrackedEntityInstances( List<String> searchKeys, Collection<OrganisationUnit> orgunits,
+        Boolean followup, Integer statusEnrollment )
+    {
+        return trackedEntityInstanceStore.countSearch( searchKeys, orgunits, followup, statusEnrollment );
+    }
+
 }

=== modified file 'dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/hibernate/HibernateTrackedEntityInstanceStore.java'
--- dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/hibernate/HibernateTrackedEntityInstanceStore.java	2014-04-22 23:37:46 +0000
+++ dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/hibernate/HibernateTrackedEntityInstanceStore.java	2014-04-23 20:15:31 +0000
@@ -243,7 +243,7 @@
         final String wordEnd = statementBuilder.getRegexpWordEnd();
 
         String sql = "from trackedentityinstance tei " + 
-            "inner join trackedentity te on tei.trackedentityid = te.trackedentityid " + 
+            "inner join trackedentity te on tei.trackedentityid = te.trackedentityid " +
             "inner join organisationunit ou on tei.organisationunitid = ou.organisationunitid ";
 
         for ( QueryItem item : params.getAttributesAndFilters() )
@@ -252,7 +252,7 @@
 
             final String joinClause = item.hasFilter() ? "inner join" : "left join";
 
-            sql += joinClause + " " +
+            sql += joinClause + " " + 
                 "trackedentityattributevalue as " + col + " " + "on " + col + ".trackedentityinstanceid = tei.trackedentityinstanceid " + 
                 "and " + col + ".trackedentityattributeid = " + item.getItem().getId() + " ";
 
@@ -261,9 +261,9 @@
                 for ( QueryFilter filter : item.getFilters() )
                 {
                     final String encodedFilter = statementBuilder.encode( filter.getFilter(), false );
-    
+
                     final String queryCol = item.isNumeric() ? (col + ".value") : "lower(" + col + ".value)";
-    
+
                     sql += "and " + queryCol + " " + filter.getSqlOperator() + " "
                         + StringUtils.lowerCase( filter.getSqlFilter( encodedFilter ) ) + " ";
                 }
@@ -303,19 +303,19 @@
 
         if ( params.hasProgram() )
         {
-            sql += hlp.whereAnd() + " exists (" + 
+            sql += hlp.whereAnd() + " exists (" +
                 "select pi.trackedentityinstanceid " +
                 "from programinstance pi ";
-            
+
             if ( params.hasEventStatus() )
             {
                 sql += 
                     "left join programstageinstance psi " +
-                    "on pi.programinstanceid = psi.programinstanceid ";                    
+                    "on pi.programinstanceid = psi.programinstanceid ";
             }
-            
-            sql +=
-                "where pi.trackedentityinstanceid = tei.trackedentityinstanceid " + 
+
+            sql += 
+                "where pi.trackedentityinstanceid = tei.trackedentityinstanceid " +
                 "and pi.programid = " + params.getProgram().getId() + " ";
 
             if ( params.hasProgramStatus() )
@@ -332,16 +332,16 @@
             {
                 sql += "and pi.enrollmentdate >= '" + getMediumDateString( params.getProgramStartDate() ) + "' ";
             }
-            
+
             if ( params.hasProgramEndDate() )
             {
                 sql += "and pi.enrollmentdate <= '" + getMediumDateString( params.getProgramEndDate() ) + "' ";
             }
-            
+
             if ( params.hasEventStatus() )
             {
                 sql += getEventStatusWhereClause( params );
-            }   
+            }
 
             sql += ") ";
         }
@@ -380,33 +380,43 @@
     {
         String start = getMediumDateString( params.getEventStartDate() );
         String end = getMediumDateString( params.getEventEndDate() );
-        
+
         String sql = StringUtils.EMPTY;
-        
+
         if ( params.isEventStatus( EventStatus.COMPLETED ) )
         {
-            sql = "and psi.executiondate >= '" + start + "' and psi.executiondate <= '" + end + "' and psi.completed = true ";
+            sql = 
+                "and psi.executiondate >= '" + start + "' and psi.executiondate <= '" + end + "' " +
+                "and psi.completed = true ";
         }
         else if ( params.isEventStatus( EventStatus.VISITED ) )
         {
-            sql = "and psi.executiondate >= '" + start + "' and psi.executiondate <= '" + end + "' and psi.completed = false ";
+            sql = 
+                "and psi.executiondate >= '" + start + "' and psi.executiondate <= '" + end + "' " + 
+                "and psi.completed = false ";
         }
         else if ( params.isEventStatus( EventStatus.FUTURE_VISIT ) )
         {
-            sql = "and psi.duedate >= '" + start + "' and psi.duedate <= '" + end + "' and psi.status is not null and date(now()) < date(psi.duedate) ";
+            sql = 
+                "and psi.executiondate is null and psi.duedate >= '" + start + "' and psi.duedate <= '" + end + "' " +
+                "and psi.status is not null and date(now()) <= date(psi.duedate) ";
         }
         else if ( params.isEventStatus( EventStatus.LATE_VISIT ) )
         {
-            sql = "and psi.duedate >= '" + start + "' and psi.duedate <= '" + end + "' and psi.status is not null and date(now()) > date(psi.duedate) ";
+            sql = 
+                "and psi.executiondate is null and psi.duedate >= '" + start + "' and psi.duedate <= '" + end + "' " +
+                "and psi.status is not null and date(now()) > date(psi.duedate) ";
         }
         else if ( params.isEventStatus( EventStatus.SKIPPED ) )
         {
-            sql = "and psi.duedate >= '" + start + "' and psi.duedate <= '" + end + "' and psi.status = " + SKIPPED_STATUS + " "; 
+            sql = 
+                "and psi.duedate >= '" + start + "' and psi.duedate <= '" + end + "' " +
+                "and psi.status = " + SKIPPED_STATUS + " ";
         }
-        
+
         return sql;
     }
-        
+
     @Override
     @SuppressWarnings( "unchecked" )
     public Collection<TrackedEntityInstance> getByOrgUnit( OrganisationUnit organisationUnit, Integer min, Integer max )
@@ -631,7 +641,7 @@
             throw new RuntimeException( ex );
         }
     }
-    
+
     @Override
     public List<Integer> getProgramStageInstances( List<String> searchKeys, Collection<OrganisationUnit> orgunits,
         Boolean followup, Collection<TrackedEntityAttribute> attributes, Integer statusEnrollment, Integer min,
@@ -1068,4 +1078,39 @@
 
         return entityInstances;
     }
+
+    @Override
+    public Collection<TrackedEntityInstance> search( List<String> searchKeys, Collection<OrganisationUnit> orgunits,
+        Boolean followup, Collection<TrackedEntityAttribute> attributes, Integer statusEnrollment, Integer min,
+        Integer max )
+    {
+        String sql = searchTrackedEntityInstanceSql( false, searchKeys, orgunits, followup, attributes,
+            statusEnrollment, min, max );
+        Collection<TrackedEntityInstance> instances = new HashSet<TrackedEntityInstance>();
+        try
+        {
+            instances = jdbcTemplate.query( sql, new RowMapper<TrackedEntityInstance>()
+            {
+                public TrackedEntityInstance mapRow( ResultSet rs, int rowNum )
+                    throws SQLException
+                {
+                    return get( rs.getInt( 1 ) );
+                }
+            } );
+        }
+        catch ( Exception ex )
+        {
+            ex.printStackTrace();
+        }
+        return instances;
+    }
+
+    @Override
+    public int countSearch( List<String> searchKeys, Collection<OrganisationUnit> orgunits, Boolean followup,
+        Integer statusEnrollment )
+    {
+        String sql = searchTrackedEntityInstanceSql( true, searchKeys, orgunits, followup, null, statusEnrollment,
+            null, null );
+        return jdbcTemplate.queryForObject( sql, Integer.class );
+    }
 }