← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 8119: Auto-send SMS - Allow define many template message for each period to send.

 

------------------------------------------------------------
revno: 8119
committer: Tran Chau <tran.hispvietnam@xxxxxxxxx>
branch nick: dhis2
timestamp: Tue 2012-09-18 15:31:07 +0700
message:
  Auto-send SMS - Allow define many template message for each period to send.
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStage.java
  dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/hibernate/HibernateProgramStageInstanceStore.java
  dhis-2/dhis-services/dhis-service-patient/src/main/resources/org/hisp/dhis/program/hibernate/ProgramStage.hbm.xml
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/programstage/AddProgramStageAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/programstage/UpdateProgramStageAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/org/hisp/dhis/patient/i18n_module.properties
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/addProgramStageForm.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/addProgramStageForm.js
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/programStage.js
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/updateProgramStageForm.js
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/updateProgramStageForm.vm


--
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/ProgramStage.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStage.java	2012-09-11 06:12:20 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStage.java	2012-09-18 08:31:07 +0000
@@ -31,6 +31,7 @@
 
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.dataentryform.DataEntryForm;
+import org.hisp.dhis.patient.PatientReminder;
 
 /**
  * @author Abyot Asalefew
@@ -39,9 +40,7 @@
     extends BaseIdentifiableObject
 {
     public static final String TYPE_DEFAULT = "default";
-
     public static final String TYPE_SECTION = "section";
-
     public static final String TYPE_CUSTOM = "custom";
     
     public static final String TEMPLATE_MESSSAGE_PATIENT_NAME = "{patient-name}";
@@ -76,9 +75,7 @@
 
     private String reportDateDescription;
     
-    private Integer daysAllowedSendMessage;
-    
-    private String templateMessage;
+    private Set<PatientReminder> patientReminders = new HashSet<PatientReminder>();
     
     // -------------------------------------------------------------------------
     // Constructors
@@ -137,12 +134,22 @@
     // -------------------------------------------------------------------------
     // Getters and setters
     // -------------------------------------------------------------------------
-
+    
     public DataEntryForm getDataEntryForm()
     {
         return dataEntryForm;
     }
 
+    public Set<PatientReminder> getPatientReminders()
+    {
+        return patientReminders;
+    }
+
+    public void setPatientReminders( Set<PatientReminder> patientReminders )
+    {
+        this.patientReminders = patientReminders;
+    }
+
     public void setDataEntryForm( DataEntryForm dataEntryForm )
     {
         this.dataEntryForm = dataEntryForm;
@@ -163,26 +170,6 @@
         this.programStageSections = programStageSections;
     }
 
-    public Integer getDaysAllowedSendMessage()
-    {
-        return daysAllowedSendMessage;
-    }
-
-    public void setDaysAllowedSendMessage( Integer daysAllowedSendMessage )
-    {
-        this.daysAllowedSendMessage = daysAllowedSendMessage;
-    }
-
-    public String getTemplateMessage()
-    {
-        return templateMessage;
-    }
-
-    public void setTemplateMessage( String templateMessage )
-    {
-        this.templateMessage = templateMessage;
-    }
-
     public Integer getStandardInterval()
     {
         return standardInterval;

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/hibernate/HibernateProgramStageInstanceStore.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/hibernate/HibernateProgramStageInstanceStore.java	2012-09-17 03:32:13 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/hibernate/HibernateProgramStageInstanceStore.java	2012-09-18 08:31:07 +0000
@@ -271,27 +271,29 @@
 
     public Collection<SchedulingProgramObject> getSendMesssageEvents()
     {
-        String sql = "select psi.programstageinstanceid, p.phonenumber, ps.templatemessage, p.firstname, org.name as orgunitName "
-            + " ,pg.name as programName, ps.name as programStageName, psi.duedate,(DATE(now()) - DATE(psi.duedate) ) as days_since_due_date "
-            + " ,psi.duedate "
-            + " from patient p INNER JOIN programinstance pi " 
-            + "         ON p.patientid=pi.patientid "
-            + " INNER JOIN programstageinstance psi " 
-            + "         ON psi.programinstanceid=pi.programinstanceid "
-            + " INNER JOIN program pg " 
-            + "         ON pg.programid=pi.programid " 
-            + " INNER JOIN programstage ps "
-            + "         ON ps.programstageid=psi.programstageid "
-            + " INNER JOIN organisationunit org "
-            + "         ON org.organisationunitid = p.organisationunitid "
-            + " WHERE pi.completed=false and psi.completed=false "
-            + "         and p.phonenumber is not NULL and p.phonenumber != '' "
-            + "         and ps.templatemessage is not NULL and ps.templatemessage != '' "
-            + "         and pg.type=1 and ps.daysallowedsendmessage is not null "
-            + "         and (  DATE(now()) - DATE(psi.duedate) ) = ps.daysallowedsendmessage ";
+        String sql = "select psi.programstageinstanceid, p.phonenumber, prm.templatemessage, p.firstname, p.middlename, p.lastname, org.name as orgunitName "
+            + ",pg.name as programName, ps.name as programStageName, psi.duedate,(DATE(now()) - DATE(psi.duedate) ) as days_since_due_date,psi.duedate "
+            + "from patient p INNER JOIN programinstance pi "
+            + "     ON p.patientid=pi.patientid "
+            + " INNER JOIN programstageinstance psi  "
+            + "     ON psi.programinstanceid=pi.programinstanceid "
+            + " INNER JOIN program pg  "
+            + "     ON pg.programid=pi.programid "
+            + " INNER JOIN programstage ps  "
+            + "     ON ps.programstageid=psi.programstageid "
+            + " INNER JOIN organisationunit org  "
+            + "     ON org.organisationunitid = p.organisationunitid "
+            + " INNER JOIN patientreminder prm  "
+            + "     ON prm.programstageid = ps.programstageid "
+            + "WHERE pi.completed=false  "
+            + "     and p.phonenumber is not NULL and p.phonenumber != '' "
+            + "     and prm.templatemessage is not NULL and prm.templatemessage != '' "
+            + "     and pg.type=1 and prm.daysallowedsendmessage is not null  "
+            + "     and psi.executiondate is null "
+            + "     and (  DATE(now()) - DATE(psi.duedate) ) = prm.daysallowedsendmessage ";
 
         SqlRowSet rs = jdbcTemplate.queryForRowSet( sql );
-        
+
         int cols = rs.getMetaData().getColumnCount();
 
         Collection<SchedulingProgramObject> schedulingProgramObjects = new HashSet<SchedulingProgramObject>();
@@ -301,7 +303,7 @@
             String message = "";
             for ( int i = 1; i <= cols; i++ )
             {
-                 
+
                 message = rs.getString( "templatemessage" );
                 String patientName = rs.getString( "firstName" );
                 String organisationunitName = rs.getString( "orgunitName" );
@@ -309,7 +311,7 @@
                 String programStageName = rs.getString( "programStageName" );
                 String daysSinceDueDate = rs.getString( "days_since_due_date" );
                 String dueDate = rs.getString( "duedate" );
-                
+
                 message = message.replace( ProgramStage.TEMPLATE_MESSSAGE_PATIENT_NAME, patientName );
                 message = message.replace( ProgramStage.TEMPLATE_MESSSAGE_PROGRAM_NAME, programName );
                 message = message.replace( ProgramStage.TEMPLATE_MESSSAGE_PROGAM_STAGE_NAME, programStageName );
@@ -319,11 +321,11 @@
             }
 
             SchedulingProgramObject schedulingProgramObject = new SchedulingProgramObject();
-            schedulingProgramObject.setProgramStageInstanceId(rs.getInt( "programstageinstanceid" ) );
+            schedulingProgramObject.setProgramStageInstanceId( rs.getInt( "programstageinstanceid" ) );
             schedulingProgramObject.setPhoneNumber( rs.getString( "phonenumber" ) );
             schedulingProgramObject.setMessage( message );
-            
-            schedulingProgramObjects.add(schedulingProgramObject);
+
+            schedulingProgramObjects.add( schedulingProgramObject );
         }
 
         return schedulingProgramObjects;
@@ -435,7 +437,7 @@
         sql += where; // filters
 
         sql = sql.substring( 0, sql.length() - 1 ) + " "; // Remove last comma
-        
+
         return sql;
     }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/resources/org/hisp/dhis/program/hibernate/ProgramStage.hbm.xml'
--- dhis-2/dhis-services/dhis-service-patient/src/main/resources/org/hisp/dhis/program/hibernate/ProgramStage.hbm.xml	2012-09-10 02:46:35 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/resources/org/hisp/dhis/program/hibernate/ProgramStage.hbm.xml	2012-09-18 08:31:07 +0000
@@ -41,9 +41,10 @@
     
     <property name="reportDateDescription" />
     
-    <property name="daysAllowedSendMessage" />
-     
-    <property name="templateMessage" />
+    <set name="patientReminders" order-by="daysAllowedSendMessage" cascade="all">
+      <key column="programStageid" />
+      <one-to-many class="org.hisp.dhis.patient.PatientReminder" />
+    </set>
     
   </class>
 </hibernate-mapping>

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/programstage/AddProgramStageAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/programstage/AddProgramStageAction.java	2012-09-10 02:46:35 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/programstage/AddProgramStageAction.java	2012-09-18 08:31:07 +0000
@@ -28,10 +28,13 @@
  */
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementService;
+import org.hisp.dhis.patient.PatientReminder;
 import org.hisp.dhis.program.Program;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.program.ProgramStage;
@@ -160,18 +163,18 @@
         this.reportDateDescription = reportDateDescription;
     }
 
-    private Integer daysAllowedSendMessage;
+    private List<Integer> daysAllowedSendMessages = new ArrayList<Integer>();
 
-    public void setDaysAllowedSendMessage( Integer daysAllowedSendMessage )
+    public void setDaysAllowedSendMessages( List<Integer> daysAllowedSendMessages )
     {
-        this.daysAllowedSendMessage = daysAllowedSendMessage;
+        this.daysAllowedSendMessages = daysAllowedSendMessages;
     }
 
-    private String templateMessage;
+    private List<String> templateMessages = new ArrayList<String>();
 
-    public void setTemplateMessage( String templateMessage )
+    public void setTemplateMessages( List<String> templateMessages )
     {
-        this.templateMessage = templateMessage;
+        this.templateMessages = templateMessages;
     }
 
     // -------------------------------------------------------------------------
@@ -182,6 +185,9 @@
         throws Exception
     {
 
+        minDaysFromStart = (minDaysFromStart == null) ? 0 : minDaysFromStart;
+        irregular = (irregular == null) ? false : irregular;
+        
         ProgramStage programStage = new ProgramStage();
 
         Program program = programService.getProgram( id );
@@ -192,15 +198,17 @@
         programStage.setProgram( program );
         programStage.setStandardInterval( standardInterval );
         programStage.setReportDateDescription( reportDateDescription );
-        programStage.setDaysAllowedSendMessage( daysAllowedSendMessage );
-        programStage.setTemplateMessage( templateMessage );
-
-        irregular = (irregular == null) ? false : irregular;
         programStage.setIrregular( irregular );
-
-        minDaysFromStart = (minDaysFromStart == null) ? 0 : minDaysFromStart;
         programStage.setMinDaysFromStart( minDaysFromStart );
-
+        
+        Set<PatientReminder> patientReminders = new HashSet<PatientReminder>();
+        for ( int i = 0; i < daysAllowedSendMessages.size(); i++ )
+        {
+            PatientReminder reminder = new PatientReminder( "", daysAllowedSendMessages.get( i ), templateMessages.get( i ));
+            patientReminders.add( reminder );
+        }
+        programStage.setPatientReminders( patientReminders );
+        
         programStageService.saveProgramStage( programStage );
 
         for ( int i = 0; i < this.selectedDataElementsValidator.size(); i++ )

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/programstage/UpdateProgramStageAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/programstage/UpdateProgramStageAction.java	2012-09-10 02:46:35 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/programstage/UpdateProgramStageAction.java	2012-09-18 08:31:07 +0000
@@ -34,6 +34,7 @@
 
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementService;
+import org.hisp.dhis.patient.PatientReminder;
 import org.hisp.dhis.program.ProgramStage;
 import org.hisp.dhis.program.ProgramStageDataElement;
 import org.hisp.dhis.program.ProgramStageDataElementService;
@@ -155,18 +156,18 @@
         this.reportDateDescription = reportDateDescription;
     }
     
-    private Integer daysAllowedSendMessage;
+    private List<Integer> daysAllowedSendMessages = new ArrayList<Integer>();
 
-    public void setDaysAllowedSendMessage( Integer daysAllowedSendMessage )
+    public void setDaysAllowedSendMessages( List<Integer> daysAllowedSendMessages )
     {
-        this.daysAllowedSendMessage = daysAllowedSendMessage;
+        this.daysAllowedSendMessages = daysAllowedSendMessages;
     }
 
-    private String templateMessage;
+    private List<String> templateMessages = new ArrayList<String>();
 
-    public void setTemplateMessage( String templateMessage )
+    public void setTemplateMessages( List<String> templateMessages )
     {
-        this.templateMessage = templateMessage;
+        this.templateMessages = templateMessages;
     }
     
     // -------------------------------------------------------------------------
@@ -176,20 +177,25 @@
     public String execute()
         throws Exception
     {
+        minDaysFromStart = (minDaysFromStart == null) ? 0 : minDaysFromStart;
+        irregular = (irregular == null) ? false : irregular;
+        
         ProgramStage programStage = programStageService.getProgramStage( id );
 
         programStage.setName( name );
         programStage.setDescription( description );
         programStage.setStandardInterval( standardInterval );
         programStage.setReportDateDescription( reportDateDescription );
-        programStage.setDaysAllowedSendMessage( daysAllowedSendMessage );
-        programStage.setTemplateMessage( templateMessage );
-
-        minDaysFromStart = (minDaysFromStart == null) ? 0 : minDaysFromStart;
         programStage.setMinDaysFromStart( minDaysFromStart );
-
-        irregular = (irregular == null) ? false : irregular;
         programStage.setIrregular( irregular );
+        
+        Set<PatientReminder> patientReminders = new HashSet<PatientReminder>();
+        for ( int i = 0; i < this.daysAllowedSendMessages.size(); i++ )
+        {
+            PatientReminder reminder = new PatientReminder( "", daysAllowedSendMessages.get( i ), templateMessages.get( i ));
+            patientReminders.add( reminder );
+        }
+        programStage.setPatientReminders( patientReminders );
 
         programStageService.updateProgramStage( programStage );
 

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/org/hisp/dhis/patient/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/org/hisp/dhis/patient/i18n_module.properties	2012-09-17 06:40:26 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/org/hisp/dhis/patient/i18n_module.properties	2012-09-18 08:31:07 +0000
@@ -269,8 +269,7 @@
 identifiers_and_attributes = Identifiers / Attributes
 displayed_in_list = Displayed in list
 report_date_description = Description of report date
-days_before_due_date = Days before due date
-days_after_due_date = Days after due date
+days_before_after_due_date = Days before/after due date
 template_message = Template reminder message
 params = Parameters
 patient_name = Person name
@@ -288,9 +287,12 @@
 scheduling_is = Scheduling is
 not_started = not started
 running = active
-negative_numbers = Negative numbers
 gateway_type = Gateway type
 execute = Execute
 time_for_sending_message = Time for sending message
 number_of_attributes = The number of attributes
-number_of_identifier_types = The number of identifier types
\ No newline at end of file
+number_of_identifier_types = The number of identifier types
+reminder = Reminder
+define_template_message = Define template message
+remove_reminder = Remove reminder
+add_more = Add more ...
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/addProgramStageForm.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/addProgramStageForm.vm	2012-09-11 03:54:32 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/addProgramStageForm.vm	2012-09-18 08:31:07 +0000
@@ -2,81 +2,47 @@
 
 <h3>$i18n.getString( "create_new_program_stage" )</h3>
 																		
-<form id="addProgramStageForm" name="addProgramStageForm" action="addProgramStage.action" method="post">
+<form id="addProgramStageForm" name="addProgramStageForm" action="addProgramStage.action" method="get">
 	<input type="hidden" id="id" name="id" value="$program.id"/>
-
+	<select id='daysAllowedSendMessages' name="daysAllowedSendMessages" multiple="multiple" class="hidden"></select>
+	<select id='templateMessages' name="templateMessages" multiple="multiple" class="hidden"></select>
 <table>
 	<thead>
 		<tr><th colspan="2">$i18n.getString( "program_stage_details" )</th></tr>
 	</thead>
-	<tbody>
-		
-		<tr>
-			<td><label>$i18n.getString( "name" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
-			<td><input type="text" id="name" name="name" class="{validate:{required:true,rangelength:[4,160]}}"/></td>
-		</tr>	
-		
-		<tr>
-			<td><label>$i18n.getString( "description" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
-			<td><input type="text" id="description" name="description" class="{validate:{required:true,minlength:4}}"/></td>
-		</tr>
-			
-		<tr>
-			<td><label>$i18n.getString( "scheduled_days_from_start" )</label></td>
-			<td><input type="text" id="minDaysFromStart" name="minDaysFromStart" class="{validate:{number:true,min:0}}"/></td>
-		</tr>
+		
+	<tr>
+		<td><label>$i18n.getString( "name" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
+		<td><input type="text" id="name" name="name" class="{validate:{required:true,rangelength:[4,160]}}"/></td>
+	</tr>	
+	
+	<tr>
+		<td><label>$i18n.getString( "description" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
+		<td><input type="text" id="description" name="description" class="{validate:{required:true,minlength:4}}"/></td>
+	</tr>
+		
+	<tr>
+		<td><label>$i18n.getString( "scheduled_days_from_start" )</label></td>
+		<td><input type="text" id="minDaysFromStart" name="minDaysFromStart" class="{validate:{number:true,min:0}}"/></td>
+	</tr>
 
-		<tr>
-			<td><label>$i18n.getString( "repeatable" )</label></td>
-			<td><input type="checkbox" id="irregular" name="irregular" value='true' onchange='repeatableOnChange();' /></td>
-		</tr>	
-		
-		<tr>
-			<td><label>$i18n.getString( "standard_interval_days" )</label></td>
-			<td><input type="text" id="standardInterval" name="standardInterval" class="{validate:{required:true,number:true}}" disabled /></td>
-		</tr>
-		
-		<tr>
-			<td><label>$i18n.getString( "report_date_description" )<em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
-			<td><input type="text" id="reportDateDescription" name="reportDateDescription" class="{validate:{required:true}}" /></td>
-		</tr>
-		
-		<tr>
-			<th colspan='2'>$i18n.getString( "template_message" )</th>
-		</tr>
-		
-		<tr>
-			<td><label>$i18n.getString( "days_after_due_date" )</label></td>
-			<td><input type="text" id="daysAllowedSendMessage" name="daysAllowedSendMessage" class="{validate:{number:true}}"/></td>
-		</tr>
-		<tr>
-			<td></td>
-			<td><i>($i18n.getString("negative_numbers") = $i18n.getString( "days_before_due_date" ))</i></td>
-		</tr>
-		
-		<tr><td>&nbsp;</td></tr>
-		
-		<tr>
-			<td>$i18n.getString( "params" )</td>
-			<td>
-				<select multiple size='6' ondblclick="insertParams(this.value);">
-					<option value="{patient-name}">$i18n.getString("patient_name")</option>
-					<option value="{program-name}">$i18n.getString("program_name")</option>
-					<option value="{program-stage-name}">$i18n.getString("program_stage_name")</option>
-					<option value="{due-date}">$i18n.getString("due_date")</option>
-					<option value="{orgunit-name}">$i18n.getString("orgunit_name")</option>
-					<option value="{days-since-due-date}">$i18n.getString("days_since_due_date")</option>
-				</select>
-			</td>
-		</tr>
-		
-		<tr>
-			<td><label>$i18n.getString( "template_message" )</label></td>
-			<td><textarea id="templateMessage" name="templateMessage" style="width:320px"></textarea></td>
-		</tr>
-		
+	<tr>
+		<td><label>$i18n.getString( "repeatable" )</label></td>
+		<td><input type="checkbox" id="irregular" name="irregular" value='true' onchange='repeatableOnChange();' /></td>
+	</tr>	
+	
+	<tr>
+		<td><label>$i18n.getString( "standard_interval_days" )</label></td>
+		<td><input type="text" id="standardInterval" name="standardInterval" class="{validate:{required:true,number:true}}" disabled /></td>
+	</tr>
+	
+	<tr>
+		<td><label>$i18n.getString( "report_date_description" )<em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
+		<td><input type="text" id="reportDateDescription" name="reportDateDescription" class="{validate:{required:true}}" /></td>
+	</tr>
+	
+	
 		<tr><td>&nbsp;</td><td>&nbsp;</td></tr> 
-	</thead>
 </table>
 
 <table id="programStageMembersArea">    
@@ -124,9 +90,51 @@
             <a href="javascript:moveUpDataElement()"><img src="../images/move_up.png"/></a><br/><br/>
             <a href="javascript:moveDownDataElement()"><img src="../images/move_down.png"/></a><br/><br/>
         </td>  
-		 </tr>
+		</tr>
     </tbody>
-</table>
+	<tr>
+		<th colspan='3'>$i18n.getString("define_template_message")</th>
+	</tr>
+</table>
+
+<table>
+	<tbody id='programStageMessage'>
+		<tr name="tr1">
+			<td colspan='2'>
+				$i18n.getString( "reminder" ) 1
+				<span style="align:right"><a href='javascript:removeTemplateMessageForm(1)'> ( $i18n.getString("remove_reminder") )</a>
+			</td>
+		</tr>
+		<tr name="tr1">
+			<td><label>$i18n.getString( "days_before_after_due_date" )</label></td>
+			<td><input type="text" id="daysAllowedSendMessage1" name="daysAllowedSendMessage" class="daysAllowedSendMessage {validate:{required:true,number:true}}"/></td>
+		</tr>
+		<tr name="tr1">
+			<td>$i18n.getString( "params" )</td>
+			<td>
+				<select multiple size='4' ondblclick="insertParams(this.value, 1);">
+					<option value="{patient-name}">$i18n.getString("patient_name")</option>
+					<option value="{program-name}">$i18n.getString("program_name")</option>
+					<option value="{program-stage-name}">$i18n.getString("program_stage_name")</option>
+					<option value="{due-date}">$i18n.getString("due_date")</option>
+					<option value="{days-since-due-date}">$i18n.getString("days_since_due_date")</option>
+					<option value="{orgunit-name}">$i18n.getString("orgunit_name")</option>
+				</select>
+			</td>
+		</tr>
+		<tr name="tr1">
+			<td><label>$i18n.getString( "template_message" )</label></td>
+			<td><textarea id="templateMessage1" name="templateMessage1" style="width:320px" class="templateMessage {validate:{required:true}}"></textarea></td>
+		</tr>
+	</tbody>
+	<tr>
+		<td></td>
+		<td>
+			<input type="button" value="$i18n.getString('add_more')" onclick='generateTemplateMessageForm();'>
+		</td>
+	</tr>
+</table>
+
 <p>
 	<input type="submit" value="$i18n.getString( 'add' )"/>
 	<input type="button" value="$i18n.getString( 'cancel' )" onclick="window.location.href='programStage.action?id=$program.id'" />
@@ -138,5 +146,16 @@
     var i18n_invalid_min_max_days = '$encoder.jsEscape( $i18n.getString( "invalid_min_max_days" ) , "'")';
     var i18n_value_must_positive = '$encoder.jsEscape( $i18n.getString( "value_must_positive" ) , "'")';
     var i18n_value_must_integer = '$encoder.jsEscape( $i18n.getString( "value_must_integer" ) , "'")';
-    var i18n_compulsory_checkbox_title = '$encoder.jsEscape( $i18n.getString( "compulsory_checkbox_title" ) , "'")';   
+    var i18n_compulsory_checkbox_title = '$encoder.jsEscape( $i18n.getString( "compulsory_checkbox_title" ) , "'")';   	
+	var i18n_reminder = '$encoder.jsEscape( $i18n.getString( "reminder" ) , "'")';   
+	var i18n_remove_reminder = '$encoder.jsEscape( $i18n.getString( "remove_reminder" ) , "'")';   
+	var i18n_days_before_after_due_date = '$encoder.jsEscape( $i18n.getString( "days_before_after_due_date" ) , "'")';   
+	var i18n_params = '$encoder.jsEscape( $i18n.getString( "params" ) , "'")';   
+	var i18n_patient_name = '$encoder.jsEscape( $i18n.getString( "patient_name" ) , "'")';   
+	var i18n_program_name = '$encoder.jsEscape( $i18n.getString( "program_name" ) , "'")';   
+	var i18n_program_stage_name = '$encoder.jsEscape( $i18n.getString( "program_stage_name" ) , "'")';   
+	var i18n_due_date = '$encoder.jsEscape( $i18n.getString( "due_date" ) , "'")';   
+	var i18n_orgunit_name = '$encoder.jsEscape( $i18n.getString( "orgunit_name" ) , "'")';   
+	var i18n_days_since_due_date = '$encoder.jsEscape( $i18n.getString( "days_since_due_date" ) , "'")';   
+	var i18n_template_message = '$encoder.jsEscape( $i18n.getString( "template_message" ) , "'")';   
 </script>
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/addProgramStageForm.js'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/addProgramStageForm.js	2012-06-04 10:03:56 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/addProgramStageForm.js	2012-09-18 08:31:07 +0000
@@ -5,9 +5,12 @@
 	}, function(){
 		var selectedDataElementsValidator = jQuery( "#selectedDataElementsValidator" );
 		selectedDataElementsValidator.empty();
-		
 		var compulsories = jQuery( "#compulsories" );
 		compulsories.empty();
+		var daysAllowedSendMessages = jQuery( "#daysAllowedSendMessages" );
+		daysAllowedSendMessages.empty();
+		var templateMessages = jQuery( "#templateMessages" );
+		templateMessages.empty();
 		
 		allowProvidedElsewhere = jQuery( "#allowProvidedElsewhere" );
 		allowProvidedElsewhere.empty();
@@ -24,6 +27,12 @@
 			checked = allowProvided.attr('checked') ? true : false;
 			allowProvidedElsewhere.append( "<option value='" + checked + "' selected='true'>" + checked + "</option>" );
 		});
+		jQuery(".daysAllowedSendMessage").each( function( i, item ){ 
+			daysAllowedSendMessages.append( "<option value='" + item.value + "' selected='true'>" + item.value +"</option>" );
+		});
+		jQuery(".templateMessage").each( function( i, item ){ 
+			templateMessages.append( "<option value='" + item.value + "' selected='true'>" +item.value+"</option>" );
+		});
 	});
 	
 	jQuery("#availableList").dhisAjaxSelect({

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/programStage.js'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/programStage.js	2012-09-17 06:40:26 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/programStage.js	2012-09-18 08:31:07 +0000
@@ -130,7 +130,6 @@
 //Move Table Row Up and Down
 //-----------------------------------------------------------------------------
 
-
 function moveUpDataElement()
 {
 	var selectedList = jQuery("#selectedList");
@@ -225,8 +224,49 @@
 	}
 }
 
-function insertParams( paramValue )
+function insertParams( paramValue, rowId )
 {
 	var templateMessage = paramValue;
-	insertTextCommon('templateMessage', templateMessage);
+	insertTextCommon('templateMessage' + rowId, templateMessage);
+}
+
+// --------------------------------------------------------------------
+// 
+// --------------------------------------------------------------------
+
+function generateTemplateMessageForm()
+{
+	var rowId = jQuery('.daysAllowedSendMessage').length + 1;
+	
+	var contend = '<tr name="tr' + rowId + '">'
+				+ 	'<td colspan="2">' + i18n_reminder + ' ' + rowId + '<a href="javascript:removeTemplateMessageForm('+ rowId +')"> ( '+ i18n_remove_reminder + ' )</a></td>'
+				+ '</tr>'
+				+ '<tr name="tr' + rowId + '">'
+				+ 	'<td><label>' + i18n_days_before_after_due_date + '</label></td>'
+				+ 	'<td><input type="text" id="daysAllowedSendMessage' + rowId + '" name="daysAllowedSendMessage' + rowId + '" class="daysAllowedSendMessage {validate:{required:true,number:true}}"/></td>'
+				+ '</tr>'
+				+ '<tr name="tr' + rowId + '">'
+				+	'<td>' + i18n_params + '</td>'
+				+	'<td>'
+				+		'<select multiple size="4" id="params' + rowId +'" name="params" ondblclick="insertParams(this.value, ' + rowId + ');">'
+				+			'<option value="{patient-name}">' + i18n_patient_name + '</option>'
+				+			'<option value="{program-name}">' + i18n_program_name + '</option>'
+				+			'<option value="{program-stage-name}">' + i18n_program_stage_name + '</option>'
+				+			'<option value="{due-date}">' + i18n_due_date + '</option>'
+				+			'<option value="{days-since-due-date}">' + i18n_days_since_due_date + '</option>'
+				+			'<option value="{orgunit-name}">' + i18n_orgunit_name + '</option>'
+				+		'</select>'
+				+	'</td>'
+				+ '</tr>'
+				+ '<tr name="tr' + rowId + '">'
+				+	'<td><label>' + i18n_template_message + '</label></td>'
+				+	'<td><textarea id="templateMessage' + rowId + '" name="templateMessage' + rowId + '" style="width:320px" class="templateMessage {validate:{required:true}}"></textarea></td>'
+				+ '</tr>';
+
+	jQuery('#programStageMessage').append( contend );
+}
+
+function removeTemplateMessageForm( rowId )
+{
+	jQuery("[name=tr" + rowId + "]").remove();
 }
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/updateProgramStageForm.js'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/updateProgramStageForm.js	2012-06-04 10:03:56 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/updateProgramStageForm.js	2012-09-18 08:31:07 +0000
@@ -3,11 +3,14 @@
 	validation( 'updateProgramStageForm', function( form ){ 
 		form.submit() ;
 	}, function(){
-		selectedDataElementsValidator = jQuery( "#selectedDataElementsValidator" );
+		var selectedDataElementsValidator = jQuery( "#selectedDataElementsValidator" );
 		selectedDataElementsValidator.empty();
-		
-		compulsories = jQuery( "#compulsories" );
+		var compulsories = jQuery( "#compulsories" );
 		compulsories.empty();
+		var daysAllowedSendMessages = jQuery( "#daysAllowedSendMessages" );
+		daysAllowedSendMessages.empty();
+		var templateMessages = jQuery( "#templateMessages" );
+		templateMessages.empty();
 		
 		allowProvidedElsewhere = jQuery( "#allowProvidedElsewhere" );
 		allowProvidedElsewhere.empty();
@@ -25,6 +28,12 @@
 			checked = allowProvided.attr('checked') ? true : false;
 			allowProvidedElsewhere.append( "<option value='" + checked + "' selected='true'>" + checked + "</option>" );
 		});
+		jQuery(".daysAllowedSendMessage").each( function( i, item ){ 
+			daysAllowedSendMessages.append( "<option value='" + item.value + "' selected='true'>" + item.value +"</option>" );
+		});
+		jQuery(".templateMessage").each( function( i, item ){ 
+			templateMessages.append( "<option value='" + item.value + "' selected='true'>" +item.value+"</option>" );
+		});
 	});
 	
 	checkValueIsExist( "name", "validateProgramStage.action", {id:getFieldValue('id')});	

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/updateProgramStageForm.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/updateProgramStageForm.vm	2012-09-17 03:32:13 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/updateProgramStageForm.vm	2012-09-18 08:31:07 +0000
@@ -4,7 +4,9 @@
 
 <form id="updateProgramStageForm" name="updateProgramStageForm" action="updateProgramStage.action" method="post">
 	<input type="hidden" id="id" name="id" value="$programStage.id"/>
-	  
+	<select id='daysAllowedSendMessages' name="daysAllowedSendMessages" multiple="multiple" class="hidden"></select>
+	<select id='templateMessages' name="templateMessages" multiple="multiple" class="hidden"></select>
+	
 	<table id="detailsList">
 		<thead>
 			<tr><th colspan="2">$i18n.getString( "program_stage_details" )</th></tr>
@@ -41,45 +43,6 @@
 				<td><label>$i18n.getString( "report_date_description" )<em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
 				<td><input type="text" id="reportDateDescription" name="reportDateDescription" value='$!programStage.reportDateDescription' class="{validate:{required:true}}" /></td>
 			</tr>
-			
-			
-			<tr>
-				<th colspan='2'>$i18n.getString( "template_message" )</th>
-			</tr>
-			
-			<tr>
-				<td><label>$i18n.getString( "days_after_due_date" )</label></td>
-				<td><input type="text" id="daysAllowedSendMessage" name="daysAllowedSendMessage" class="{validate:{number:true}}" value="$!programStage.daysAllowedSendMessage"/></td>
-			</tr>
-			
-			<tr>
-				<td></td>
-				<td><i>($i18n.getString("negative_numbers") = $i18n.getString( "days_before_due_date" ))</i></td>
-			</tr>
-		
-			<tr><td>&nbsp;</td></tr>
-		
-			<tr>
-				<td>$i18n.getString( "params" )</td>
-				<td>
-					<select multiple size='6' ondblclick="insertParams(this.value);">
-						<option value="{patient-name}">$i18n.getString("patient_name")</option>
-						<option value="{program-name}">$i18n.getString("program_name")</option>
-						<option value="{program-stage-name}">$i18n.getString("program_stage_name")</option>
-						<option value="{due-date}">$i18n.getString("due_date")</option>
-						<option value="{orgunit-name}">$i18n.getString("orgunit_name")</option>
-						<option value="{days-since-due-date}">$i18n.getString("days_since_due_date")</option>
-					</select>
-				</td>
-			</tr>
-			
-			<tr>
-				<td><label>$i18n.getString( "template_message" )</label></td>
-				<td><textarea id="templateMessage" name="templateMessage" style="width:320px">$!programStage.templateMessage</textarea></td>
-			</tr>
-			
-			<tr><td>&nbsp;</td></tr>       
-		  
 		</tbody>
 	</table>
 
@@ -141,7 +104,52 @@
 			
 		</tr>
 		</tbody>
-	</table>
+		<tr><th colspan='3'>$i18n.getString("define_template_message")</th></tr>
+	</table>
+	
+	<table>
+		<tbody id='programStageMessage'>
+			#set($index = 0)
+			#foreach($reminder in $programStage.patientReminders)
+			#set($index = $index + 1)
+				<tr name="tr$index">
+					<td colspan='2'>
+						$i18n.getString( "reminder" ) $index
+						<span style="align:right"><a href='javascript:removeTemplateMessageForm($index)'> ( $i18n.getString("remove_reminder") )</a>
+					</td>
+				</tr>
+				<tr name="tr$index">
+					<td><label>$i18n.getString( "days_before_after_due_date" )</label></td>
+					<td><input type="text" id="daysAllowedSendMessage$index" name="daysAllowedSendMessage$index" class="daysAllowedSendMessage {validate:{required:true,number:true}}" value="$!reminder.daysAllowedSendMessage"/></td>
+				</tr>
+				<tr name="tr$index">
+					<td>$i18n.getString( "params" )</td>
+					<td>
+						<select multiple size='4' ondblclick="insertParams(this.value, $index);">
+							<option value="{patient-name}">$i18n.getString("patient_name")</option>
+							<option value="{program-name}">$i18n.getString("program_name")</option>
+							<option value="{program-stage-name}">$i18n.getString("program_stage_name")</option>
+							<option value="{due-date}">$i18n.getString("due_date")</option>
+							<option value="{days-since-due-date}">$i18n.getString("days_since_due_date")</option>
+							<option value="{orgunit-name}">$i18n.getString("orgunit_name")</option>
+						</select>
+					</td>
+				</tr>
+				<tr name="tr$index">
+					<td><label>$i18n.getString( "template_message" )</label></td>
+					<td><textarea id="templateMessage$index" name="templateMessage$index" style="width:320px" class="templateMessage {validate:{required:true}}">$reminder.templateMessage</textarea></td>
+				</tr>
+			#end
+		</tbody>
+		
+		<tr>
+			<td></td>
+			<td>
+				<input type="button" value="$i18n.getString('add_more')" onclick='generateTemplateMessageForm();'>
+			</td>
+		</tr>
+	</table>
+	
 	<p>
 		<input type="submit" value="$i18n.getString( 'update' )" />
 		<input type="button" value="$i18n.getString( 'cancel' )" onclick="window.location.href='programStage.action?id=$programStage.program.id'" />
@@ -154,4 +162,15 @@
     var i18n_value_must_positive = '$encoder.jsEscape( $i18n.getString( "value_must_positive" ) , "'")';
     var i18n_value_must_integer = '$encoder.jsEscape( $i18n.getString( "value_must_integer" ) , "'")';
     var i18n_compulsory_checkbox_title = '$encoder.jsEscape( $i18n.getString( "compulsory_checkbox_title" ) , "'")';      
+	var i18n_reminder = '$encoder.jsEscape( $i18n.getString( "reminder" ) , "'")';   
+	var i18n_remove_reminder = '$encoder.jsEscape( $i18n.getString( "remove_reminder" ) , "'")';   
+	var i18n_params = '$encoder.jsEscape( $i18n.getString( "params" ) , "'")';   
+	var i18n_patient_name = '$encoder.jsEscape( $i18n.getString( "patient_name" ) , "'")';   
+	var i18n_program_name = '$encoder.jsEscape( $i18n.getString( "program_name" ) , "'")';   
+	var i18n_program_stage_name = '$encoder.jsEscape( $i18n.getString( "program_stage_name" ) , "'")';   
+	var i18n_due_date = '$encoder.jsEscape( $i18n.getString( "due_date" ) , "'")';   
+	var i18n_orgunit_name = '$encoder.jsEscape( $i18n.getString( "orgunit_name" ) , "'")';   
+	var i18n_days_since_due_date = '$encoder.jsEscape( $i18n.getString( "days_since_due_date" ) , "'")';   
+	var i18n_template_message = '$encoder.jsEscape( $i18n.getString( "template_message" ) , "'")';   
+	var i18n_days_before_after_due_date = '$encoder.jsEscape( $i18n.getString( "days_before_after_due_date" ) , "'")';   
 </script>
\ No newline at end of file