← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 15877: both programinstance and programstageinstance can now have multiple comments

 

------------------------------------------------------------
revno: 15877
committer: Abyot Asalefew Gizaw abyota@xxxxxxxxx
branch nick: dhis2
timestamp: Fri 2014-06-27 12:55:57 +0200
message:
  both programinstance and programstageinstance can now have multiple comments
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramInstance.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStageInstance.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/AbstractEnrollmentService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/Enrollment.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/AbstractEventService.java
  dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/program/DefaultProgramInstanceService.java
  dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/program/ProgramInstanceDeletionHandler.java
  dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/program/hibernate/ProgramInstance.hbm.xml
  dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/program/hibernate/ProgramStageInstance.hbm.xml


--
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/program/ProgramInstance.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramInstance.java	2014-06-20 12:32:01 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramInstance.java	2014-06-27 10:55:57 +0000
@@ -62,14 +62,23 @@
      * Determines if a de-serialized file is compatible with this class.
      */
     private static final long serialVersionUID = -1235315582356509653L;
+
     public static int STATUS_ACTIVE = 0;
+
     private Integer status = STATUS_ACTIVE;
+
     public static int STATUS_COMPLETED = 1;
+
     public static int STATUS_CANCELLED = 2;
+
     private int id;
-    private Date dateOfIncident; //TODO rename to incidenceDate
+
+    private Date dateOfIncident; // TODO rename to incidenceDate
+
     private Date enrollmentDate;
+
     private Date endDate;
+
     private TrackedEntityInstance entityInstance;
 
     private Program program;
@@ -82,7 +91,7 @@
 
     private Boolean followup = false;
 
-    private TrackedEntityComment comment;
+    private List<TrackedEntityComment> comments = new ArrayList<TrackedEntityComment>();
 
     // -------------------------------------------------------------------------
     // Constructors
@@ -108,9 +117,9 @@
     /**
      * Updated the bi-directional associations between this program instance and
      * the given entity instance and program.
-     *
+     * 
      * @param entityInstance the entity instance to enroll.
-     * @param program        the program to enroll the entity instance to.
+     * @param program the program to enroll the entity instance to.
      */
     public void enrollTrackedEntityInstance( TrackedEntityInstance entityInstance, Program program )
     {
@@ -393,14 +402,17 @@
         this.messageConversations = messageConversations;
     }
 
-    public TrackedEntityComment getComment()
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public List<TrackedEntityComment> getComments()
     {
-        return comment;
+        return comments;
     }
 
-    public void setComment( TrackedEntityComment comment )
+    public void setComments( List<TrackedEntityComment> comments )
     {
-        this.comment = comment;
+        this.comments = comments;
     }
 
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStageInstance.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStageInstance.java	2014-06-20 13:05:15 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStageInstance.java	2014-06-27 10:55:57 +0000
@@ -65,7 +65,7 @@
 
     private List<MessageConversation> messageConversations = new ArrayList<MessageConversation>();
 
-    private TrackedEntityComment comment;
+    private List<TrackedEntityComment> comments = new ArrayList<TrackedEntityComment>();
 
     private EventStatus status = EventStatus.ACTIVE;
 
@@ -243,14 +243,14 @@
         this.latitude = latitude;
     }
 
-    public TrackedEntityComment getComment()
+    public List<TrackedEntityComment> getComments()
     {
-        return comment;
+        return comments;
     }
 
-    public void setComment( TrackedEntityComment comment )
+    public void setComments( List<TrackedEntityComment> comments )
     {
-        this.comment = comment;
+        this.comments = comments;
     }
 
     public EventStatus getStatus()

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/AbstractEnrollmentService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/AbstractEnrollmentService.java	2014-05-17 12:04:42 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/AbstractEnrollmentService.java	2014-06-27 10:55:57 +0000
@@ -36,6 +36,7 @@
 import org.hisp.dhis.common.OrganisationUnitSelectionMode;
 import org.hisp.dhis.common.QueryItem;
 import org.hisp.dhis.common.QueryOperator;
+import org.hisp.dhis.dxf2.events.event.Note;
 import org.hisp.dhis.dxf2.events.trackedentity.Attribute;
 import org.hisp.dhis.dxf2.events.trackedentity.TrackedEntityInstance;
 import org.hisp.dhis.dxf2.events.trackedentity.TrackedEntityInstanceService;
@@ -56,12 +57,16 @@
 import org.hisp.dhis.trackedentity.TrackedEntityInstanceQueryParams;
 import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValue;
 import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValueService;
+import org.hisp.dhis.trackedentitycomment.TrackedEntityComment;
+import org.hisp.dhis.trackedentitycomment.TrackedEntityCommentService;
+import org.hisp.dhis.user.CurrentUserService;
 import org.hisp.dhis.user.UserService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.Assert;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
@@ -88,6 +93,12 @@
 
     @Autowired
     private TrackedEntityAttributeValueService trackedEntityAttributeValueService;
+    
+    @Autowired
+    protected CurrentUserService currentUserService;
+    
+    @Autowired
+    private TrackedEntityCommentService commentService;
 
     @Autowired
     private IdentifiableObjectManager manager;
@@ -127,7 +138,8 @@
     @Override
     public Enrollments getEnrollments( TrackedEntityInstance trackedEntityInstance )
     {
-        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( trackedEntityInstance.getTrackedEntityInstance() );
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( trackedEntityInstance
+            .getTrackedEntityInstance() );
 
         return getEnrollments( entityInstance );
     }
@@ -135,7 +147,8 @@
     @Override
     public Enrollments getEnrollments( TrackedEntityInstance trackedEntityInstance, EnrollmentStatus status )
     {
-        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( trackedEntityInstance.getTrackedEntityInstance() );
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( trackedEntityInstance
+            .getTrackedEntityInstance() );
         return getEnrollments( entityInstance, status );
     }
 
@@ -148,7 +161,8 @@
     }
 
     @Override
-    public Enrollments getEnrollments( org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance, EnrollmentStatus status )
+    public Enrollments getEnrollments( org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance,
+        EnrollmentStatus status )
     {
         List<ProgramInstance> programInstances = new ArrayList<ProgramInstance>(
             programInstanceService.getProgramInstances( entityInstance, status.getValue() ) );
@@ -202,14 +216,17 @@
     @Override
     public Enrollments getEnrollments( Program program, TrackedEntityInstance trackedEntityInstance )
     {
-        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( trackedEntityInstance.getTrackedEntityInstance() );
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( trackedEntityInstance
+            .getTrackedEntityInstance() );
         return getEnrollments( programInstanceService.getProgramInstances( entityInstance, program ) );
     }
 
     @Override
-    public Enrollments getEnrollments( Program program, TrackedEntityInstance trackedEntityInstance, EnrollmentStatus status )
+    public Enrollments getEnrollments( Program program, TrackedEntityInstance trackedEntityInstance,
+        EnrollmentStatus status )
     {
-        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( trackedEntityInstance.getTrackedEntityInstance() );
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( trackedEntityInstance
+            .getTrackedEntityInstance() );
         return getEnrollments( programInstanceService.getProgramInstances( entityInstance, program, status.getValue() ) );
     }
 
@@ -254,6 +271,23 @@
         enrollment.setDateOfEnrollment( programInstance.getEnrollmentDate() );
         enrollment.setDateOfIncident( programInstance.getDateOfIncident() );
 
+        List<TrackedEntityComment> comments = programInstance.getComments();
+
+        for ( TrackedEntityComment comment : comments )
+        {
+            Note note = new Note();
+
+            note.setValue( comment.getCommentText() );
+            note.setStoredBy( comment.getCreator() );
+
+            if ( comment.getCreatedDate() != null )
+            {
+                note.setStoredDate( comment.getCreatedDate().toString() );
+            }
+
+            enrollment.getNotes().add( note );
+        }
+
         return enrollment;
     }
 
@@ -267,8 +301,10 @@
         ImportSummary importSummary = new ImportSummary();
         importSummary.setDataValueCount( null );
 
-        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( enrollment.getTrackedEntityInstance() );
-        TrackedEntityInstance trackedEntityInstance = trackedEntityInstanceService.getTrackedEntityInstance( entityInstance );
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( enrollment
+            .getTrackedEntityInstance() );
+        TrackedEntityInstance trackedEntityInstance = trackedEntityInstanceService
+            .getTrackedEntityInstance( entityInstance );
         Program program = getProgram( enrollment.getProgram() );
 
         Enrollments enrollments = getEnrollments( program, trackedEntityInstance, EnrollmentStatus.ACTIVE );
@@ -302,14 +338,16 @@
         if ( programInstance == null )
         {
             importSummary.setStatus( ImportStatus.ERROR );
-            importSummary.setDescription( "Could not enroll TrackedEntityInstance " + enrollment.getTrackedEntityInstance()
-                + " into program " + enrollment.getProgram() );
+            importSummary.setDescription( "Could not enroll TrackedEntityInstance "
+                + enrollment.getTrackedEntityInstance() + " into program " + enrollment.getProgram() );
 
             return importSummary;
         }
 
         updateAttributeValues( enrollment );
         programInstanceService.updateProgramInstance( programInstance );
+        
+        saveTrackedEntityComment( programInstance, enrollment );
 
         importSummary.setReference( programInstance.getUid() );
         importSummary.getImportCount().incrementImported();
@@ -358,7 +396,8 @@
             return importSummary;
         }
 
-        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( enrollment.getTrackedEntityInstance() );
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = getTrackedEntityInstance( enrollment
+            .getTrackedEntityInstance() );
         Program program = getProgram( enrollment.getProgram() );
 
         programInstance.setProgram( program );
@@ -388,6 +427,8 @@
 
         updateAttributeValues( enrollment );
         programInstanceService.updateProgramInstance( programInstance );
+        
+        saveTrackedEntityComment( programInstance, enrollment );
 
         importSummary.setReference( enrollment.getEnrollment() );
         importSummary.getImportCount().incrementImported();
@@ -436,15 +477,16 @@
         List<ImportConflict> importConflicts = new ArrayList<ImportConflict>();
 
         Program program = getProgram( enrollment.getProgram() );
-        org.hisp.dhis.trackedentity.TrackedEntityInstance trackedEntityInstance = teiService.getTrackedEntityInstance(
-            enrollment.getTrackedEntityInstance() );
+        org.hisp.dhis.trackedentity.TrackedEntityInstance trackedEntityInstance = teiService
+            .getTrackedEntityInstance( enrollment.getTrackedEntityInstance() );
 
         Map<TrackedEntityAttribute, Boolean> mandatoryMap = Maps.newHashMap();
         Map<String, String> attributeValueMap = Maps.newHashMap();
 
         for ( ProgramTrackedEntityAttribute programTrackedEntityAttribute : program.getAttributes() )
         {
-            mandatoryMap.put( programTrackedEntityAttribute.getAttribute(), programTrackedEntityAttribute.isMandatory() );
+            mandatoryMap
+                .put( programTrackedEntityAttribute.getAttribute(), programTrackedEntityAttribute.isMandatory() );
         }
 
         for ( TrackedEntityAttributeValue value : trackedEntityInstance.getAttributeValues() )
@@ -462,7 +504,8 @@
             importConflicts.addAll( validateAttributeType( attribute ) );
         }
 
-        TrackedEntityInstance instance = trackedEntityInstanceService.getTrackedEntityInstance( enrollment.getTrackedEntityInstance() );
+        TrackedEntityInstance instance = trackedEntityInstanceService.getTrackedEntityInstance( enrollment
+            .getTrackedEntityInstance() );
 
         for ( TrackedEntityAttribute trackedEntityAttribute : mandatoryMap.keySet() )
         {
@@ -470,8 +513,8 @@
 
             if ( mandatory && !attributeValueMap.containsKey( trackedEntityAttribute.getUid() ) )
             {
-                importConflicts.add( new ImportConflict( "Attribute.attribute", "Missing mandatory attribute " +
-                    trackedEntityAttribute.getUid() ) );
+                importConflicts.add( new ImportConflict( "Attribute.attribute", "Missing mandatory attribute "
+                    + trackedEntityAttribute.getUid() ) );
                 continue;
             }
 
@@ -479,9 +522,8 @@
             {
                 OrganisationUnit organisationUnit = manager.get( OrganisationUnit.class, instance.getOrgUnit() );
 
-                importConflicts.addAll(
-                    checkScope( trackedEntityInstance, trackedEntityAttribute, attributeValueMap.get( trackedEntityAttribute.getUid() ), organisationUnit, program )
-                );
+                importConflicts.addAll( checkScope( trackedEntityInstance, trackedEntityAttribute,
+                    attributeValueMap.get( trackedEntityAttribute.getUid() ), organisationUnit, program ) );
             }
 
             attributeValueMap.remove( trackedEntityAttribute.getUid() );
@@ -489,14 +531,15 @@
 
         if ( !attributeValueMap.isEmpty() )
         {
-            importConflicts.add( new ImportConflict( "Attribute.attribute", "Only program attributes is allowed for enrollment " +
-                attributeValueMap ) );
+            importConflicts.add( new ImportConflict( "Attribute.attribute",
+                "Only program attributes is allowed for enrollment " + attributeValueMap ) );
         }
 
         return importConflicts;
     }
 
-    private List<ImportConflict> checkScope( org.hisp.dhis.trackedentity.TrackedEntityInstance tei, TrackedEntityAttribute attribute, String value, OrganisationUnit organisationUnit, Program program )
+    private List<ImportConflict> checkScope( org.hisp.dhis.trackedentity.TrackedEntityInstance tei,
+        TrackedEntityAttribute attribute, String value, OrganisationUnit organisationUnit, Program program )
     {
         List<ImportConflict> importConflicts = new ArrayList<ImportConflict>();
 
@@ -526,20 +569,22 @@
 
         Grid instances = teiService.getTrackedEntityInstances( params );
 
-        if ( instances.getHeight() == 0 || (instances.getHeight() == 1 && instances.getRow( 0 ).contains( tei.getUid() )) )
+        if ( instances.getHeight() == 0
+            || (instances.getHeight() == 1 && instances.getRow( 0 ).contains( tei.getUid() )) )
         {
             return importConflicts;
         }
 
-        importConflicts.add( new ImportConflict( "Attribute.value", "Non-unique attribute value '" + value + "' for attribute " + attribute.getUid() ) );
+        importConflicts.add( new ImportConflict( "Attribute.value", "Non-unique attribute value '" + value
+            + "' for attribute " + attribute.getUid() ) );
 
         return importConflicts;
     }
 
     private void updateAttributeValues( Enrollment enrollment )
     {
-        org.hisp.dhis.trackedentity.TrackedEntityInstance trackedEntityInstance = teiService.getTrackedEntityInstance(
-            enrollment.getTrackedEntityInstance() );
+        org.hisp.dhis.trackedentity.TrackedEntityInstance trackedEntityInstance = teiService
+            .getTrackedEntityInstance( enrollment.getTrackedEntityInstance() );
         Map<String, String> attributeValueMap = Maps.newHashMap();
 
         for ( Attribute attribute : enrollment.getAttributes() )
@@ -587,7 +632,8 @@
 
     private org.hisp.dhis.trackedentity.TrackedEntityInstance getTrackedEntityInstance( String trackedEntityInstance )
     {
-        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = teiService.getTrackedEntityInstance( trackedEntityInstance );
+        org.hisp.dhis.trackedentity.TrackedEntityInstance entityInstance = teiService
+            .getTrackedEntityInstance( trackedEntityInstance );
 
         if ( entityInstance == null )
         {
@@ -613,7 +659,8 @@
     private List<ImportConflict> validateAttributeType( Attribute attribute )
     {
         List<ImportConflict> importConflicts = Lists.newArrayList();
-        TrackedEntityAttribute teAttribute = trackedEntityAttributeService.getTrackedEntityAttribute( attribute.getAttribute() );
+        TrackedEntityAttribute teAttribute = trackedEntityAttributeService.getTrackedEntityAttribute( attribute
+            .getAttribute() );
 
         if ( teAttribute == null )
         {
@@ -626,19 +673,23 @@
             importConflicts.add( new ImportConflict( "Attribute.value", "Value length is greater than 256 chars." ) );
         }
 
-        if ( TrackedEntityAttribute.TYPE_NUMBER.equals( teAttribute.getValueType() ) && !MathUtils.isNumeric( attribute.getValue() ) )
+        if ( TrackedEntityAttribute.TYPE_NUMBER.equals( teAttribute.getValueType() )
+            && !MathUtils.isNumeric( attribute.getValue() ) )
         {
             importConflicts.add( new ImportConflict( "Attribute.value", "Value is not numeric." ) );
         }
-        else if ( TrackedEntityAttribute.TYPE_BOOL.equals( teAttribute.getValueType() ) && !MathUtils.isBool( attribute.getValue() ) )
+        else if ( TrackedEntityAttribute.TYPE_BOOL.equals( teAttribute.getValueType() )
+            && !MathUtils.isBool( attribute.getValue() ) )
         {
             importConflicts.add( new ImportConflict( "Attribute.value", "Value is not boolean." ) );
         }
-        else if ( TrackedEntityAttribute.TYPE_DATE.equals( teAttribute.getValueType() ) && !DateUtils.dateIsValid( attribute.getValue() ) )
+        else if ( TrackedEntityAttribute.TYPE_DATE.equals( teAttribute.getValueType() )
+            && !DateUtils.dateIsValid( attribute.getValue() ) )
         {
             importConflicts.add( new ImportConflict( "Attribute.value", "Value is not date." ) );
         }
-        else if ( TrackedEntityAttribute.TYPE_TRUE_ONLY.equals( teAttribute.getValueType() ) && "true".equals( attribute.getValue() ) )
+        else if ( TrackedEntityAttribute.TYPE_TRUE_ONLY.equals( teAttribute.getValueType() )
+            && "true".equals( attribute.getValue() ) )
         {
             importConflicts.add( new ImportConflict( "Attribute.value", "Value is not true (true-only value type)." ) );
         }
@@ -646,14 +697,35 @@
         {
             if ( userService.getUserCredentialsByUsername( attribute.getValue() ) == null )
             {
-                importConflicts.add( new ImportConflict( "Attribute.value", "Value is not pointing to a valid username." ) );
+                importConflicts.add( new ImportConflict( "Attribute.value",
+                    "Value is not pointing to a valid username." ) );
             }
         }
-        else if ( TrackedEntityAttribute.TYPE_OPTION_SET.equals( teAttribute.getValueType() ) && !teAttribute.getOptionSet().getOptions().contains( attribute.getValue() ) )
+        else if ( TrackedEntityAttribute.TYPE_OPTION_SET.equals( teAttribute.getValueType() )
+            && !teAttribute.getOptionSet().getOptions().contains( attribute.getValue() ) )
         {
             importConflicts.add( new ImportConflict( "Attribute.value", "Value is not pointing to a valid option." ) );
         }
 
         return importConflicts;
     }
+    
+    private void saveTrackedEntityComment( ProgramInstance programInstance, Enrollment enrollment )
+    {
+        String storedBy = currentUserService.getCurrentUsername();
+        
+        for ( Note note : enrollment.getNotes() )
+        {
+            TrackedEntityComment comment = new TrackedEntityComment();
+            comment.setCreator( storedBy );
+            comment.setCreatedDate( new Date() );
+            comment.setCommentText( note.getValue() );
+
+            commentService.addTrackedEntityComment( comment );
+
+            programInstance.getComments().add( comment );
+
+            programInstanceService.updateProgramInstance( programInstance );
+        }
+    }
 }
\ No newline at end of file

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/Enrollment.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/Enrollment.java	2014-03-18 13:20:03 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/Enrollment.java	2014-06-27 10:55:57 +0000
@@ -32,9 +32,11 @@
 import com.fasterxml.jackson.annotation.JsonView;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
+import org.hisp.dhis.dxf2.events.event.Note;
 import org.hisp.dhis.dxf2.events.trackedentity.Attribute;
 
 import java.util.ArrayList;
@@ -60,6 +62,8 @@
     private Date dateOfIncident;
 
     private List<Attribute> attributes = new ArrayList<Attribute>();
+    
+    private List<Note> notes = new ArrayList<Note>();
 
     public Enrollment()
     {
@@ -149,6 +153,19 @@
     {
         this.attributes = attributes;
     }
+    
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public List<Note> getNotes()
+    {
+        return notes;
+    }
+
+    public void setNotes( List<Note> notes )
+    {
+        this.notes = notes;
+    }
 
     @Override
     public boolean equals( Object o )
@@ -166,6 +183,7 @@
             return false;
         if ( program != null ? !program.equals( that.program ) : that.program != null ) return false;
         if ( status != that.status ) return false;
+        if ( notes != null ? !notes.equals( that.notes ) : that.notes != null ) return false;
 
         return true;
     }
@@ -180,6 +198,7 @@
         result = 31 * result + (dateOfEnrollment != null ? dateOfEnrollment.hashCode() : 0);
         result = 31 * result + (dateOfIncident != null ? dateOfIncident.hashCode() : 0);
         result = 31 * result + (attributes != null ? attributes.hashCode() : 0);
+        result = 31 * result + (notes != null ? notes.hashCode() : 0);
         return result;
     }
 
@@ -194,6 +213,7 @@
             ", dateOfEnrollment=" + dateOfEnrollment +
             ", dateOfIncident=" + dateOfIncident +
             ", attributes=" + attributes +
+            ", notes=" + notes +
             '}';
     }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/AbstractEventService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/AbstractEventService.java	2014-06-20 14:17:48 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/AbstractEventService.java	2014-06-27 10:55:57 +0000
@@ -542,11 +542,9 @@
             event.getDataValues().add( value );
         }
 
-        ProgramInstance programInstance = programStageInstance.getProgramInstance();
-
-        TrackedEntityComment comment = programInstance.getComment();
-
-        if ( comment != null )
+        List<TrackedEntityComment> comments = programStageInstance.getComments();
+
+        for ( TrackedEntityComment comment : comments )
         {
             Note note = new Note();
 
@@ -787,7 +785,7 @@
 
             commentService.addTrackedEntityComment( comment );
 
-            programInstance.setComment( comment );
+            programInstance.getComments().add( comment );
 
             programInstanceService.updateProgramInstance( programInstance );
         }

=== modified file 'dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/program/DefaultProgramInstanceService.java'
--- dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/program/DefaultProgramInstanceService.java	2014-06-20 12:32:01 +0000
+++ dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/program/DefaultProgramInstanceService.java	2014-06-27 10:55:57 +0000
@@ -141,14 +141,14 @@
     }
 
     private TrackedEntityInstanceService trackedEntityInstanceService;
-    
+
     public void setTrackedEntityInstanceService( TrackedEntityInstanceService trackedEntityInstanceService )
     {
         this.trackedEntityInstanceService = trackedEntityInstanceService;
     }
 
     private I18nManager i18nManager;
-    
+
     public void setI18nManager( I18nManager i18nManager )
     {
         this.i18nManager = i18nManager;
@@ -256,7 +256,7 @@
 
     public List<Grid> getProgramInstanceReport( TrackedEntityInstance instance, I18n i18n )
     {
-        
+
         List<Grid> grids = new ArrayList<Grid>();
 
         // ---------------------------------------------------------------------
@@ -324,7 +324,7 @@
     public Grid getProgramInstanceReport( ProgramInstance programInstance, I18n i18n )
     {
         I18nFormat format = i18nManager.getI18nFormat();
-        
+
         Grid grid = new ListGrid();
 
         // ---------------------------------------------------------------------
@@ -369,8 +369,9 @@
 
         // Get entityInstance comments for the program instance
 
-        TrackedEntityComment comment = programInstance.getComment();
-        if ( comment != null )
+        List<TrackedEntityComment> comments = programInstance.getComments();
+
+        for ( TrackedEntityComment comment : comments )
         {
             grid.addRow();
             grid.addValue( i18n.getString( "comment" ) + " " + i18n.getString( "on" ) + " "
@@ -439,7 +440,7 @@
 
         return result;
     }
-    
+
     @Override
     public ProgramInstance enrollTrackedEntityInstance( TrackedEntityInstance entityInstance, Program program,
         Date enrollmentDate, Date dateOfIncident, OrganisationUnit organisationUnit )
@@ -515,7 +516,8 @@
             messages = new ArrayList<MessageConversation>();
         }
 
-        messages.addAll( sendMessageConversations( programInstance, TrackedEntityInstanceReminder.SEND_WHEN_TO_EMROLLEMENT ) );
+        messages.addAll( sendMessageConversations( programInstance,
+            TrackedEntityInstanceReminder.SEND_WHEN_TO_EMROLLEMENT ) );
 
         updateProgramInstance( programInstance );
         trackedEntityInstanceService.updateTrackedEntityInstance( entityInstance );
@@ -530,7 +532,7 @@
 
         for ( ProgramStageInstance stageInstance : stageInstances )
         {
-            if ( (!stageInstance.isCompleted() && stageInstance.getStatus()!= EventStatus.SKIPPED )
+            if ( (!stageInstance.isCompleted() && stageInstance.getStatus() != EventStatus.SKIPPED)
                 || stageInstance.getProgramStage().getIrregular() )
             {
                 return false;
@@ -554,8 +556,8 @@
             outboundSms = new ArrayList<OutboundSms>();
         }
 
-        outboundSms.addAll( sendMessages( programInstance,
-            TrackedEntityInstanceReminder.SEND_WHEN_TO_C0MPLETED_PROGRAM ) );
+        outboundSms
+            .addAll( sendMessages( programInstance, TrackedEntityInstanceReminder.SEND_WHEN_TO_C0MPLETED_PROGRAM ) );
 
         // -----------------------------------------------------------------
         // Send DHIS message when to completed the program
@@ -666,7 +668,7 @@
     private void getProgramStageInstancesReport( Grid grid, ProgramInstance programInstance, I18n i18n )
     {
         I18nFormat format = i18nManager.getI18nFormat();
-        
+
         Collection<ProgramStageInstance> programStageInstances = programInstance.getProgramStageInstances();
 
         for ( ProgramStageInstance programStageInstance : programStageInstances )
@@ -734,7 +736,7 @@
         TrackedEntityInstance entityInstance )
     {
         I18nFormat format = i18nManager.getI18nFormat();
-        
+
         Set<String> phoneNumbers = reminderService.getPhonenumbers( reminder, entityInstance );
         OutboundSms outboundSms = null;
 
@@ -788,7 +790,7 @@
     private Collection<MessageConversation> sendMessageConversations( ProgramInstance programInstance, int status )
     {
         I18nFormat format = i18nManager.getI18nFormat();
-        
+
         Collection<MessageConversation> messageConversations = new HashSet<MessageConversation>();
 
         Collection<TrackedEntityInstanceReminder> reminders = programInstance.getProgram().getInstanceReminders();

=== modified file 'dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/program/ProgramInstanceDeletionHandler.java'
--- dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/program/ProgramInstanceDeletionHandler.java	2014-06-03 04:55:04 +0000
+++ dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/program/ProgramInstanceDeletionHandler.java	2014-06-27 10:55:57 +0000
@@ -33,6 +33,7 @@
 
 import org.hisp.dhis.system.deletion.DeletionHandler;
 import org.hisp.dhis.trackedentity.TrackedEntityInstance;
+import org.hisp.dhis.trackedentitycomment.TrackedEntityComment;
 import org.hisp.dhis.trackedentitycomment.TrackedEntityCommentService;
 import org.hisp.dhis.trackedentitydatavalue.TrackedEntityDataValue;
 import org.hisp.dhis.trackedentitydatavalue.TrackedEntityDataValueService;
@@ -109,7 +110,10 @@
                 programStageInstanceService.deleteProgramStageInstance( programStageInstance );
             }
 
-            commentService.deleteTrackedEntityComment( programInstance.getComment() );
+            for( TrackedEntityComment comment : programInstance.getComments())
+            {
+                commentService.deleteTrackedEntityComment( comment );
+            }
 
             programInstanceService.deleteProgramInstance( programInstance );
         }

=== modified file 'dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/program/hibernate/ProgramInstance.hbm.xml'
--- dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/program/hibernate/ProgramInstance.hbm.xml	2014-02-07 20:25:49 +0000
+++ dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/program/hibernate/ProgramInstance.hbm.xml	2014-06-27 10:55:57 +0000
@@ -54,9 +54,15 @@
 				column="messageconversationid" />
 		</list>
 
-		<many-to-one name="comment" cascade="all"
+		<list name="comments" table="programinstancecomments" cascade="all">
+            <key column="programinstanceid"/>
+            <list-index column="sort_order" base="1" />
+            <many-to-many column="trackedentitycommentid" unique="true" class="org.hisp.dhis.trackedentitycomment.TrackedEntityComment"/>
+        </list>
+        
+		<!--<many-to-one name="comment" cascade="all"
 			class="org.hisp.dhis.trackedentitycomment.TrackedEntityComment"
-			column="trackedentitycommentid" foreign-key="fk_programinstance_commentid" />
+			column="trackedentitycommentid" foreign-key="fk_programinstance_commentid" />-->
 
 	</class>
 </hibernate-mapping>

=== modified file 'dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/program/hibernate/ProgramStageInstance.hbm.xml'
--- dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/program/hibernate/ProgramStageInstance.hbm.xml	2014-06-20 12:32:01 +0000
+++ dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/program/hibernate/ProgramStageInstance.hbm.xml	2014-06-27 10:55:57 +0000
@@ -53,9 +53,15 @@
 		<property name="completedUser" />
 
 		<property name="completedDate" />
+
+		<list name="comments" table="programstageinstancecomments" cascade="all"> 
+            <key column="programstageinstanceid"/>
+            <list-index column="sort_order" base="1" />
+            <many-to-many column="trackedentitycommentid" unique="true" class="org.hisp.dhis.trackedentitycomment.TrackedEntityComment"/>
+        </list>
 		
-		<many-to-one name="comment" cascade="all" class="org.hisp.dhis.trackedentitycomment.TrackedEntityComment" 
-		    column="trackedentitycommentid" foreign-key="fk_programinstance_commentid" />
+		<!--<many-to-one name="comment" cascade="all" class="org.hisp.dhis.trackedentitycomment.TrackedEntityComment" 
+		    column="trackedentitycommentid" foreign-key="fk_programinstance_commentid" />-->
 
 	</class>
 </hibernate-mapping>