dhis2-devs team mailing list archive
-
dhis2-devs team
-
Mailing list archive
-
Message #08403
[Branch ~dhis2-devs-core/dhis2/trunk] Rev 2015: Auto-update isDeath property of Patient if the reason of unrollement from program is Death.
------------------------------------------------------------
revno: 2015
committer: Tran Chau <tran.hispvietnam@xxxxxxxxx>
branch nick: dhis2
timestamp: Tue 2010-11-09 13:45:07 +0700
message:
Auto-update isDeath property of Patient if the reason of unrollement from program is Death.
removed:
dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/TableAlteror.java
added:
dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/startup/
dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/startup/ProgramAttributePopulator.java
dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/startup/TableAlteror.java
modified:
dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramAttribute.java
dhis-2/dhis-services/dhis-service-patient/src/main/resources/META-INF/dhis/beans.xml
dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/patient/RemoveEnrollmentAction.java
dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/org/hisp/dhis/patient/i18n_module.properties
--
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/ProgramAttribute.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramAttribute.java 2010-11-09 02:09:53 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramAttribute.java 2010-11-09 06:45:07 +0000
@@ -38,6 +38,9 @@
public class ProgramAttribute
implements Serializable
{
+ // -------------------------------------------------------------------------
+ // Define ValueType
+ // -------------------------------------------------------------------------
public static final String TYPE_DATE = "DATE";
public static final String TYPE_STRING = "TEXT";
@@ -48,7 +51,17 @@
public static final String TYPE_COMBO = "COMBO";
- public final char REASON_IS_DEAD = 'd';
+ // -------------------------------------------------------------------------
+ // Default Program Attributes
+ // -------------------------------------------------------------------------
+
+ public static final String DEAD_NAME = "Dead";
+
+ public static final String CLOSED_DATE = "Closed Date";
+
+ // -------------------------------------------------------------------------
+ // Properties
+ // -------------------------------------------------------------------------
private Integer id;
@@ -60,8 +73,6 @@
private Set<ProgramAttributeOption> attributeOptions;
- // private String causeDeath;
-
// -------------------------------------------------------------------------
// Constructors
// -------------------------------------------------------------------------
=== removed file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/TableAlteror.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/TableAlteror.java 2010-10-29 12:19:15 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/TableAlteror.java 1970-01-01 00:00:00 +0000
@@ -1,109 +0,0 @@
-package org.hisp.dhis.patient;
-
-import java.sql.ResultSet;
-import java.sql.Statement;
-
-import org.amplecode.quick.StatementHolder;
-import org.amplecode.quick.StatementManager;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-public class TableAlteror
-{
- private static final Log log = LogFactory.getLog( TableAlteror.class );
-
- // -------------------------------------------------------------------------
- // Dependencies
- // -------------------------------------------------------------------------
-
- private StatementManager statementManager;
-
- public void setStatementManager( StatementManager statementManager )
- {
- this.statementManager = statementManager;
- }
-
- public void execute()
- throws Exception
- {
- updatePatientOrgunitAssociation();
-
- updateDOBType();
-
- executeSql("UPDATE patientidentifiertype SET type='" + PatientIdentifierType.VALUE_TYPE_TEXT +"' WHERE type IS NULL");
-
- executeSql("UPDATE program SET minDaysAllowedInputData=0 WHERE minDaysAllowedInputData IS NULL");
-
- executeSql("UPDATE program SET maxDaysAllowedInputData=0 WHERE maxDaysAllowedInputData IS NULL");
- }
-
- private void updatePatientOrgunitAssociation(){
-
- StatementHolder holder = statementManager.getHolder();
-
- try
- {
- Statement statement = holder.getStatement();
-
- ResultSet isUpdated = statement
- .executeQuery( "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'patientidentifier' AND COLUMN_NAME = 'organisationunitid'" );
-
- if ( isUpdated.next() )
- {
-
- ResultSet resultSet = statement
- .executeQuery( "SELECT patientid, organisationunitid FROM patientidentifier" );
- while ( resultSet.next() )
- {
- executeSql( "UPDATE patient SET organisationunitid=" + resultSet.getInt( 2 ) + " WHERE patientid="
- + resultSet.getInt( 1 ) );
- }
-
- executeSql( "ALTER TABLE patientidentifier DROP COLUMN organisationunitid" );
- }
- }
- catch ( Exception ex )
- {
- log.error( ex );
- }
- finally
- {
- holder.close();
- }
- }
-
- private void updateDOBType(){
- StatementHolder holder = statementManager.getHolder();
-
- try
- {
- executeSql( "UPDATE patient SET dobType='A' WHERE birthdateestimated=true");
-
- executeSql("ALTER TABLE patient drop column birthdateestimated");
-
- executeSql("DELETE FROM validationcriteria where property='birthdateestimated'");
- }
- catch ( Exception ex )
- {
- log.error( ex );
- }
- finally
- {
- holder.close();
- }
- }
-
- private int executeSql( String sql )
- {
- try
- {
- return statementManager.getHolder().executeUpdate( sql );
- }
- catch ( Exception ex )
- {
- log.debug( ex );
-
- return -1;
- }
- }
-}
=== added directory 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/startup'
=== added file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/startup/ProgramAttributePopulator.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/startup/ProgramAttributePopulator.java 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/startup/ProgramAttributePopulator.java 2010-11-09 06:45:07 +0000
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2004-2010, 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.
+ */
+
+package org.hisp.dhis.patient.startup;
+
+import org.hisp.dhis.program.ProgramAttribute;
+import org.hisp.dhis.program.ProgramAttributeService;
+import org.hisp.dhis.system.startup.AbstractStartupRoutine;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @author Chau Thu Tran
+ *
+ * @version ProgramAttributePopulator.java Nov 9, 2010 12:22:29 PM
+ */
+public class ProgramAttributePopulator
+ extends AbstractStartupRoutine
+{
+ // -------------------------------------------------------------------------
+ // Dependencies
+ // -------------------------------------------------------------------------
+
+ private ProgramAttributeService programAttributeService;
+
+ public void setProgramAttributeService( ProgramAttributeService programAttributeService )
+ {
+ this.programAttributeService = programAttributeService;
+ }
+ // -------------------------------------------------------------------------
+ // Execute
+ // -------------------------------------------------------------------------
+
+ @Transactional
+ public void execute()
+ throws Exception
+ {
+ ProgramAttribute attribute = programAttributeService.getProgramAttributeByName( ProgramAttribute.DEAD_NAME );
+
+ if ( attribute == null )
+ {
+ attribute = new ProgramAttribute();
+ attribute.setName( ProgramAttribute.DEAD_NAME );
+ attribute.setDescription( "Date when patient unenrolls the program" );
+ attribute.setValueType( ProgramAttribute.TYPE_BOOL );
+
+ programAttributeService.saveProgramAttribute( attribute );
+ }
+
+ attribute = programAttributeService.getProgramAttributeByName( ProgramAttribute.CLOSED_DATE );
+
+ if ( attribute == null )
+ {
+ attribute = new ProgramAttribute();
+ attribute.setName( ProgramAttribute.CLOSED_DATE );
+ attribute.setDescription( "Date when patient unenrolls the program" );
+ attribute.setValueType( ProgramAttribute.TYPE_DATE );
+
+ programAttributeService.saveProgramAttribute( attribute );
+ }
+ }
+
+}
=== added file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/startup/TableAlteror.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/startup/TableAlteror.java 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/startup/TableAlteror.java 2010-11-09 06:45:07 +0000
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2004-2010, 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.
+ */
+
+package org.hisp.dhis.patient.startup;
+
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+import org.amplecode.quick.StatementHolder;
+import org.amplecode.quick.StatementManager;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hisp.dhis.patient.PatientIdentifierType;
+import org.hisp.dhis.system.startup.AbstractStartupRoutine;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @author Chau Thu Tran
+ *
+ * @version TableAlteror.java Sep 9, 2010 10:22:29 PM
+ */
+public class TableAlteror extends AbstractStartupRoutine
+{
+ private static final Log log = LogFactory.getLog( TableAlteror.class );
+
+ // -------------------------------------------------------------------------
+ // Dependencies
+ // -------------------------------------------------------------------------
+
+ private StatementManager statementManager;
+
+ public void setStatementManager( StatementManager statementManager )
+ {
+ this.statementManager = statementManager;
+ }
+ // -------------------------------------------------------------------------
+ // Execute
+ // -------------------------------------------------------------------------
+
+ @Transactional
+ public void execute()
+ throws Exception
+ {
+ updatePatientOrgunitAssociation();
+
+ updateDOBType();
+
+ executeSql("UPDATE patientidentifiertype SET type='" + PatientIdentifierType.VALUE_TYPE_TEXT +"' WHERE type IS NULL");
+
+ executeSql("UPDATE program SET minDaysAllowedInputData=0 WHERE minDaysAllowedInputData IS NULL");
+
+ executeSql("UPDATE program SET maxDaysAllowedInputData=0 WHERE maxDaysAllowedInputData IS NULL");
+ }
+
+ private void updatePatientOrgunitAssociation(){
+
+ StatementHolder holder = statementManager.getHolder();
+
+ try
+ {
+ Statement statement = holder.getStatement();
+
+ ResultSet isUpdated = statement
+ .executeQuery( "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'patientidentifier' AND COLUMN_NAME = 'organisationunitid'" );
+
+ if ( isUpdated.next() )
+ {
+
+ ResultSet resultSet = statement
+ .executeQuery( "SELECT patientid, organisationunitid FROM patientidentifier" );
+ while ( resultSet.next() )
+ {
+ executeSql( "UPDATE patient SET organisationunitid=" + resultSet.getInt( 2 ) + " WHERE patientid="
+ + resultSet.getInt( 1 ) );
+ }
+
+ executeSql( "ALTER TABLE patientidentifier DROP COLUMN organisationunitid" );
+ }
+ }
+ catch ( Exception ex )
+ {
+ log.error( ex );
+ }
+ finally
+ {
+ holder.close();
+ }
+ }
+
+ private void updateDOBType(){
+ StatementHolder holder = statementManager.getHolder();
+
+ try
+ {
+ executeSql( "UPDATE patient SET dobType='A' WHERE birthdateestimated=true");
+
+ executeSql("ALTER TABLE patient drop column birthdateestimated");
+
+ executeSql("DELETE FROM validationcriteria where property='birthdateestimated'");
+ }
+ catch ( Exception ex )
+ {
+ log.error( ex );
+ }
+ finally
+ {
+ holder.close();
+ }
+ }
+
+ private int executeSql( String sql )
+ {
+ try
+ {
+ return statementManager.getHolder().executeUpdate( sql );
+ }
+ catch ( Exception ex )
+ {
+ log.debug( ex );
+
+ return -1;
+ }
+ }
+}
=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-patient/src/main/resources/META-INF/dhis/beans.xml 2010-11-09 02:09:53 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/resources/META-INF/dhis/beans.xml 2010-11-09 06:45:07 +0000
@@ -272,12 +272,6 @@
<property name="patientService" ref="org.hisp.dhis.patient.PatientService" />
<property name="periodService" ref="org.hisp.dhis.period.PeriodService" />
</bean>
-
- <!-- Table Alteror -->
-
- <bean id="org.hisp.dhis.patient.TableAlteror" class="org.hisp.dhis.patient.TableAlteror" init-method="execute">
- <property name="statementManager" ref="statementManager" />
- </bean>
<!-- DeletionHandlers -->
@@ -320,6 +314,35 @@
<property name="programStageDEValidationService" ref="org.hisp.dhis.program.ProgramStageDataElementValidationService"/>
</bean>
+ <!-- Startup -->
+
+ <bean id="org.hisp.dhis.patient.startup.TableAlteror" class="org.hisp.dhis.patient.startup.TableAlteror" >
+ <property name="statementManager" ref="statementManager" />
+ <property name="name" value="PatientTableAlteror" />
+ <property name="runlevel" value="4" />
+ <property name="skipInTests" value="true" />
+ </bean>
+
+ <bean id="org.hisp.dhis.patient.startup.ProgramAttributePopulator" class="org.hisp.dhis.patient.startup.ProgramAttributePopulator">
+ <property name="programAttributeService" ref="org.hisp.dhis.program.ProgramAttributeService" />
+ <property name="name" value="ProgramAttributePopulator" />
+ <property name="runlevel" value="5" />
+ </bean>
+
+ <bean
+ class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
+ <property name="targetObject"
+ ref="org.hisp.dhis.system.startup.StartupRoutineExecutor" />
+ <property name="targetMethod" value="addStartupRoutines" />
+ <property name="arguments">
+ <list>
+ <list>
+ <ref local="org.hisp.dhis.patient.startup.ProgramAttributePopulator" />
+ <ref local="org.hisp.dhis.patient.startup.TableAlteror" />
+ </list>
+ </list>
+ </property>
+ </bean>
<!-- DeletionManager -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/patient/RemoveEnrollmentAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/patient/RemoveEnrollmentAction.java 2010-11-09 02:09:53 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/patient/RemoveEnrollmentAction.java 2010-11-09 06:45:07 +0000
@@ -35,6 +35,7 @@
import javax.servlet.http.HttpServletRequest;
+import org.hisp.dhis.i18n.I18nFormat;
import org.hisp.dhis.organisationunit.OrganisationUnit;
import org.hisp.dhis.organisationunit.OrganisationUnitService;
import org.hisp.dhis.patient.state.SelectedStateManager;
@@ -120,6 +121,13 @@
this.programAttributeValueService = programAttributeValueService;
}
+ private I18nFormat format;
+
+ public void setFormat( I18nFormat format )
+ {
+ this.format = format;
+ }
+
// -------------------------------------------------------------------------
// Input/Output
// -------------------------------------------------------------------------
@@ -225,12 +233,14 @@
// -----------------------------------------------------------------------------------------------------
HttpServletRequest request = ServletActionContext.getRequest();
- System.out.println( "\n\n ++++++++++++ request : " + request );
Collection<ProgramAttribute> attributes = programAttributeService.getAllProgramAttributes();
Set<ProgramAttribute> programAttributes = new HashSet<ProgramAttribute>();
+ // End-user inputs attribute value for DEAD-attribute
+ boolean flag = false;
+
if ( attributes != null && attributes.size() > 0 )
{
programInstance.getAttributes().clear();
@@ -239,9 +249,6 @@
for ( ProgramAttribute attribute : attributes )
{
String value = request.getParameter( RemoveEnrollmentAction.PREFIX_ATTRIBUTE + attribute.getId() );
- System.out.println( "\n\n ++++++++++++ attr : " + RemoveEnrollmentAction.PREFIX_ATTRIBUTE
- + attribute.getId() );
- System.out.println( "\n\n value : " + value );
if ( StringUtils.isNotBlank( value ) )
{
@@ -256,10 +263,20 @@
attributeValue = new ProgramAttributeValue();
attributeValue.setProgramInstance( programInstance );
attributeValue.setProgramAttribute( attribute );
-
- if ( ProgramAttribute.TYPE_COMBO.equalsIgnoreCase( attribute.getValueType() ) )
- {
- ProgramAttributeOption option = programAttributeOptionService.get( NumberUtils.toInt( value, 0 ) );
+
+ // DEAD program-attribute
+ if ( attribute.getName().equalsIgnoreCase( ProgramAttribute.DEAD_NAME )
+ && attribute.getValueType().equalsIgnoreCase( ProgramAttribute.TYPE_BOOL ) )
+ {
+ attributeValue.setValue( value.trim() );
+ patient.setIsDead( Boolean.parseBoolean( value.trim() ) );
+ patientService.updatePatient( patient );
+ flag = true;
+ }
+ else if ( ProgramAttribute.TYPE_COMBO.equalsIgnoreCase( attribute.getValueType() ) )
+ {
+ ProgramAttributeOption option = programAttributeOptionService.get( NumberUtils.toInt(
+ value, 0 ) );
if ( option != null )
{
attributeValue.setProgramAttributeOption( option );
@@ -271,9 +288,17 @@
attributeValue.setValue( value.trim() );
}
+ // CLOSED-DATE program-attribute
+ if ( attribute.getName().equalsIgnoreCase( ProgramAttribute.CLOSED_DATE )
+ && attribute.getValueType().equalsIgnoreCase( ProgramAttribute.TYPE_DATE ) && flag )
+ {
+ patient.setDeathDate( format.parseDate( value.trim() ) );
+ patientService.updatePatient( patient );
+ }
+
// save values
programAttributeValueService.saveProgramAttributeValue( attributeValue );
-
+
}
// attributeValue is exist
else
=== 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 2010-11-09 02:09:53 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/org/hisp/dhis/patient/i18n_module.properties 2010-11-09 06:45:07 +0000
@@ -420,4 +420,4 @@
program_attribute_management = Program Attribute Management
add_new_program_attribute = Add New Program Attribute
update_new_program_attribute = Update New Program Attribute
-program_infor = Program information
+program_infor = Program information
\ No newline at end of file