=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/setting/SettingKey.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/setting/SettingKey.java 2016-02-09 15:26:32 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/setting/SettingKey.java 2016-02-17 10:10:29 +0000 @@ -100,6 +100,7 @@ LAST_SUCCESSFUL_ANALYTICS_TABLES_UPDATE( "keyLastSuccessfulAnalyticsTablesUpdate", Date.class ), LAST_SUCCESSFUL_RESOURCE_TABLES_UPDATE( "keyLastSuccessfulResourceTablesUpdate", Date.class ), LAST_SUCCESSFUL_MONITORING( "keyLastSuccessfulMonitoring", Date.class ), + LAST_SUCCESSFUL_SMS_SCHEDULING( "lastSuccessfulSmsScheduling", Date.class ), HELP_PAGE_LINK( "helpPageLink", "../dhis-web-commons-about/help.action", String.class ), ACCEPTANCE_REQUIRED_FOR_APPROVAL( "keyAcceptanceRequiredForApproval", Boolean.FALSE, Boolean.class ), SYSTEM_NOTIFICATIONS_EMAIL( "keySystemNotificationsEmail" ), === added directory 'dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/sms' === added directory 'dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/sms/scheduling' === added file 'dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/sms/scheduling/SendScheduledMessageTask.java' --- dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/sms/scheduling/SendScheduledMessageTask.java 1970-01-01 00:00:00 +0000 +++ dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/sms/scheduling/SendScheduledMessageTask.java 2016-02-17 10:10:29 +0000 @@ -0,0 +1,294 @@ +package org.hisp.dhis.sms.scheduling; + +/* + * Copyright (c) 2004-2016, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import static org.hisp.dhis.sms.outbound.OutboundSms.DHIS_SYSTEM_SENDER; +import static org.hisp.dhis.system.notification.NotificationLevel.INFO; + +import java.util.Collection; +import java.util.Date; +import java.util.List; + +import org.hisp.dhis.program.ProgramInstanceService; +import org.hisp.dhis.program.ProgramStageInstanceService; +import org.hisp.dhis.program.SchedulingProgramObject; +import org.hisp.dhis.sms.SmsSender; +import org.hisp.dhis.sms.SmsServiceException; +import org.hisp.dhis.sms.outbound.OutboundSms; +import org.hisp.dhis.sms.outbound.OutboundSmsService; +import org.hisp.dhis.sms.outbound.OutboundSmsStatus; +import org.hisp.dhis.system.notification.Notifier; +import org.hisp.dhis.system.util.Clock; +import org.hisp.dhis.system.util.SystemUtils; +import org.springframework.jdbc.core.JdbcTemplate; +import org.hisp.dhis.scheduling.TaskId; + +/** + * @author Chau Thu Tran + * + * @version SendScheduledMessageTask.java 12:57:53 PM Sep 10, 2012 $ + */ +public class SendScheduledMessageTask + implements Runnable +{ + private ProgramStageInstanceService programStageInstanceService; + + public void setProgramStageInstanceService( ProgramStageInstanceService programStageInstanceService ) + { + this.programStageInstanceService = programStageInstanceService; + } + + private ProgramInstanceService programInstanceService; + + public void setProgramInstanceService( ProgramInstanceService programInstanceService ) + { + this.programInstanceService = programInstanceService; + } + + private OutboundSmsService outboundSmsService; + + public void setOutboundSmsService( OutboundSmsService outboundSmsService ) + { + this.outboundSmsService = outboundSmsService; + } + + private SmsSender smsSender; + + public void setSmsSender( SmsSender smsSender ) + { + this.smsSender = smsSender; + } + + private JdbcTemplate jdbcTemplate; + + public void setJdbcTemplate( JdbcTemplate jdbcTemplate ) + { + this.jdbcTemplate = jdbcTemplate; + } + + private Notifier notifier; + + public void setNotifier( Notifier notifier ) + { + this.notifier = notifier; + } + + // ------------------------------------------------------------------------- + // Params + // ------------------------------------------------------------------------- + + private Boolean sendingMessage; + + public void setSendingMessage( Boolean sendingMessage ) + { + this.sendingMessage = sendingMessage; + } + + private Boolean sendNow; + + public void setSendNow( Boolean sendNow ) + { + this.sendNow = sendNow; + } + + private TaskId taskId; + + public void setTaskId( TaskId taskId ) + { + this.taskId = taskId; + } + + // ------------------------------------------------------------------------- + // Runnable implementation + // ------------------------------------------------------------------------- + + @Override + public void run() + { + final int cpuCores = SystemUtils.getCpuCores(); + + Clock clock = new Clock().startClock().logTime( + "Aggregate process started, number of CPU cores: " + cpuCores + ", " + SystemUtils.getMemoryString() ); + + if ( sendNow ) + { + clock.logTime( "Starting to prepare reminder messages" ); + notifier.clear( taskId ).notify( taskId, "Start to prepare reminder messages" ); + + scheduleProgramStageInstanceMessage(); + scheduleProgramInstanceMessage(); + + clock.logTime( "Preparing reminder messages completed" ); + notifier.notify( taskId, INFO, "Preparing reminder messages completed", true ); + + clock.logTime( "Starting to send messages in outbound" ); + notifier.notify( taskId, INFO, "Start to send messages in outbound", true ); + + sendMessage(); + + clock.logTime( "Sending messages in outbound completed" ); + notifier.notify( taskId, INFO, "Sending messages in outbound completed", true ); + + return; + } + + if ( sendingMessage ) + { + clock.logTime( "Starting to send messages in outbound" ); + notifier.notify( taskId, INFO, "Start to send messages in outbound", true ); + + sendMessage(); + + clock.logTime( "Sending messages in outbound completed" ); + notifier.notify( taskId, INFO, "Sending messages in outbound completed", true ); + } + else + { + clock.logTime( "Starting to prepare reminder messages" ); + notifier.clear( taskId ).notify( taskId, "Start to prepare reminder messages" ); + + scheduleProgramStageInstanceMessage(); + scheduleProgramInstanceMessage(); + + clock.logTime( "Preparing reminder messages completed" ); + notifier.notify( taskId, INFO, "Preparing reminder messages completed", true ); + } + + } + + // ------------------------------------------------------------------------- + // Supportive methods + // ------------------------------------------------------------------------- + + private void scheduleProgramStageInstanceMessage() + { + notifier.notify( taskId, "Start to prepare reminder messages for events" ); + + Collection schedulingProgramObjects = programStageInstanceService + .getSendMessageEvents(); + + for ( SchedulingProgramObject schedulingProgramObject : schedulingProgramObjects ) + { + String message = schedulingProgramObject.getMessage(); + + try + { + OutboundSms outboundSms = new OutboundSms( message, schedulingProgramObject.getPhoneNumber() ); + outboundSms.setSender( DHIS_SYSTEM_SENDER ); + outboundSmsService.saveOutboundSms( outboundSms ); + + String sortOrderSql = "SELECT max(sort_order) " + + "FROM programstageinstance_outboundsms where programstageinstanceid=" + + schedulingProgramObject.getProgramStageInstanceId(); + Integer sortOrder = jdbcTemplate.queryForObject( sortOrderSql, Integer.class ); + if ( sortOrder == null ) + { + sortOrder = 0; + } + sortOrder = sortOrder + 1; + + String sql = "INSERT INTO programstageinstance_outboundsms" + + "( programstageinstanceid, outboundsmsid, sort_order) VALUES " + "(" + + schedulingProgramObject.getProgramStageInstanceId() + ", " + outboundSms.getId() + "," + sortOrder + + ") "; + + jdbcTemplate.execute( sql ); + + notifier.notify( taskId, + "Reminder messages for event of " + outboundSms.getRecipients() + " is created " ); + } + catch ( SmsServiceException e ) + { + message = e.getMessage(); + } + } + + notifier.notify( taskId, INFO, "Preparing reminder messages for events completed", true ); + } + + private void scheduleProgramInstanceMessage() + { + notifier.notify( taskId, "Start to prepare remigetScheduledTasksnder messages for enrollements" ); + + Collection schedulingProgramObjects = programInstanceService.getScheduledMessages(); + + for ( SchedulingProgramObject schedulingProgramObject : schedulingProgramObjects ) + { + String message = schedulingProgramObject.getMessage(); + try + { + OutboundSms outboundSms = new OutboundSms( message, schedulingProgramObject.getPhoneNumber() ); + outboundSms.setSender( DHIS_SYSTEM_SENDER ); + outboundSmsService.saveOutboundSms( outboundSms ); + + String sortOrderSql = "select max(sort_order) " + + "from programinstance_outboundsms where programinstanceid=" + + schedulingProgramObject.getProgramInstanceId(); + Integer sortOrder = jdbcTemplate.queryForObject( sortOrderSql, Integer.class ); + if ( sortOrder == null ) + { + sortOrder = 0; + } + sortOrder = sortOrder + 1; + + String sql = "INSERT INTO programinstance_outboundsms" + + "( programinstanceid, outboundsmsid, sort_order) VALUES " + "(" + + schedulingProgramObject.getProgramInstanceId() + ", " + outboundSms.getId() + "," + sortOrder + + ") "; + + jdbcTemplate.execute( sql ); + + notifier.notify( taskId, + "Reminder messages for enrollement of " + outboundSms.getRecipients() + " is created " ); + } + catch ( SmsServiceException e ) + { + message = e.getMessage(); + } + } + + notifier.notify( taskId, INFO, "Sending reminder messages for enrollement completed", true ); + + } + + private void sendMessage() + { + List outboundSmsList = outboundSmsService.getOutboundSms( OutboundSmsStatus.OUTBOUND ); + + if ( outboundSmsList != null ) + { + for ( OutboundSms outboundSms : outboundSmsList ) + { + outboundSms.setDate( new Date() ); + outboundSms.setStatus( OutboundSmsStatus.SENT ); + smsSender.sendMessage( outboundSms, null ); + } + } + } +} === modified file 'dhis-2/dhis-services/dhis-service-administration/src/main/resources/META-INF/dhis/beans.xml' --- dhis-2/dhis-services/dhis-service-administration/src/main/resources/META-INF/dhis/beans.xml 2015-12-21 21:50:29 +0000 +++ dhis-2/dhis-services/dhis-service-administration/src/main/resources/META-INF/dhis/beans.xml 2016-02-17 10:10:29 +0000 @@ -89,5 +89,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + === modified file 'dhis-2/dhis-services/dhis-service-eventreporting/src/main/resources/META-INF/dhis/beans.xml' --- dhis-2/dhis-services/dhis-service-eventreporting/src/main/resources/META-INF/dhis/beans.xml 2016-02-10 14:57:19 +0000 +++ dhis-2/dhis-services/dhis-service-eventreporting/src/main/resources/META-INF/dhis/beans.xml 2016-02-17 10:10:29 +0000 @@ -75,7 +75,7 @@ + class="org.hisp.dhis.scheduling.SendScheduledMessageTask" scope="prototype"> + + === modified file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/scheduling/Scheduler.java' --- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/scheduling/Scheduler.java 2016-01-04 02:27:49 +0000 +++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/scheduling/Scheduler.java 2016-02-17 10:10:29 +0000 @@ -45,6 +45,7 @@ String CRON_EVERY_MIN = "0 0/1 * * * ?"; String CRON_EVERY_15MIN = "0 0/15 * * * ?"; String CRON_TEST = "0 * * * * ?"; + String CRON_DAILY_8AM = "0 0 8 * * ?"; /** * Execute the given task immediately. === modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/scheduling/ScheduleTasksAction.java' --- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/scheduling/ScheduleTasksAction.java 2016-01-04 02:27:49 +0000 +++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/scheduling/ScheduleTasksAction.java 2016-02-17 10:10:29 +0000 @@ -34,9 +34,13 @@ import static org.hisp.dhis.scheduling.SchedulingManager.TASK_MONITORING_LAST_DAY; import static org.hisp.dhis.scheduling.SchedulingManager.TASK_RESOURCE_TABLE; import static org.hisp.dhis.scheduling.SchedulingManager.TASK_RESOURCE_TABLE_15_MINS; +import static org.hisp.dhis.scheduling.SchedulingManager.TASK_SMS_SCHEDULER; +import static org.hisp.dhis.scheduling.SchedulingManager.TASK_SEND_SCHEDULED_SMS; import static org.hisp.dhis.system.scheduling.Scheduler.CRON_DAILY_0AM; import static org.hisp.dhis.system.scheduling.Scheduler.CRON_EVERY_15MIN; import static org.hisp.dhis.system.scheduling.Scheduler.CRON_EVERY_MIN; +import static org.hisp.dhis.system.scheduling.Scheduler.CRON_DAILY_11PM; +import static org.hisp.dhis.system.scheduling.Scheduler.CRON_DAILY_8AM; import java.util.Collection; import java.util.Date; @@ -66,6 +70,7 @@ private static final String STRATEGY_ALL_15_MIN = "allEvery15Min"; private static final String STRATEGY_LAST_3_YEARS_DAILY = "last3YearsDaily"; private static final String STRATEGY_ENABLED = "enabled"; + private static final String STRATEGY_EVERY_MIDNIGHT = "everyMidNight"; private static final Log log = LogFactory.getLog( ScheduleTasksAction.class ); @@ -143,6 +148,18 @@ { this.dataSynchStrategy = dataSynchStrategy; } + + private String smsSchedulerStrategy; + + public String getSmsSchedulerStrategy() + { + return smsSchedulerStrategy; + } + + public void setSmsSchedulerStrategy( String smsSchedulerStrategy ) + { + this.smsSchedulerStrategy = smsSchedulerStrategy; + } // ------------------------------------------------------------------------- // Output @@ -196,6 +213,13 @@ { return lastDataSyncSuccess; } + + private Date lastSmsSchedulerSuccess; + + public Date getLastSmsSchedulerSuccess() + { + return lastSmsSchedulerSuccess; + } // ------------------------------------------------------------------------- // Action implementation @@ -257,6 +281,16 @@ { cronKeyMap.putValue( CRON_EVERY_MIN, TASK_DATA_SYNCH ); } + + // ------------------------------------------------------------- + // SMS Scheduler + // ------------------------------------------------------------- + + if(STRATEGY_EVERY_MIDNIGHT.equals( smsSchedulerStrategy )) + { + cronKeyMap.putValue(CRON_DAILY_11PM, TASK_SMS_SCHEDULER); + cronKeyMap.putValue( CRON_DAILY_8AM, TASK_SEND_SCHEDULED_SMS ); + } schedulingManager.scheduleTasks( cronKeyMap ); } @@ -308,6 +342,15 @@ { dataSynchStrategy = STRATEGY_ENABLED; } + + // ------------------------------------------------------------- + // SMS Scheduler + // ------------------------------------------------------------- + + if ( keys.contains( TASK_SMS_SCHEDULER ) ) + { + smsSchedulerStrategy = STRATEGY_EVERY_MIDNIGHT; + } } status = schedulingManager.getTaskStatus(); @@ -318,6 +361,7 @@ lastResourceTableSuccess = (Date) systemSettingManager.getSystemSetting( SettingKey.LAST_SUCCESSFUL_RESOURCE_TABLES_UPDATE ); lastAnalyticsTableSuccess = (Date) systemSettingManager.getSystemSetting( SettingKey.LAST_SUCCESSFUL_ANALYTICS_TABLES_UPDATE ); lastMonitoringSuccess = (Date) systemSettingManager.getSystemSetting( SettingKey.LAST_SUCCESSFUL_MONITORING ); + lastSmsSchedulerSuccess = (Date) systemSettingManager.getSystemSetting( SettingKey.LAST_SUCCESSFUL_SMS_SCHEDULING ); lastDataSyncSuccess = synchronizationManager.getLastSynchSuccess(); log.info( "Status: " + status ); === modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/org/hisp/dhis/dataadmin/i18n_module.properties' --- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/org/hisp/dhis/dataadmin/i18n_module.properties 2015-11-26 04:04:27 +0000 +++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/org/hisp/dhis/dataadmin/i18n_module.properties 2016-02-17 10:10:29 +0000 @@ -293,6 +293,8 @@ last_2_years_daily=Last 2 years daily last_3_years_daily=Last 3 years daily all_daily=All daily +every_mid_night=Every night at 12 +execute_now=Execute Now all_every_15_min=All every 15 minutes resource_table_task_strategy=Resource tables task strategy data_mart_task_strategy=Data mart task strategy @@ -359,6 +361,8 @@ disabled=Disabled data_synchronization=Data synchronization data_synchronization_strategy=Data synchronization strategy +sms_scheduler_strategy= SMS Scheduler Strategy +sms_scheduler=SMS Scheduler enabled=Enabled last_success=Last success option_management = Option management === modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/viewScheduledTasks.vm' --- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/viewScheduledTasks.vm 2015-11-27 15:15:24 +0000 +++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/viewScheduledTasks.vm 2016-02-17 10:10:29 +0000 @@ -67,6 +67,23 @@ + + + +
$i18n.getString( "sms_scheduler")
+ +
$i18n.getString( "sms_scheduler_strategy" )
+ +
$i18n.getString( "last_success" ): $!format.formatDateTime( $lastSmsSchedulerSuccess )
+ +
+ +
+ +