← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 12140: Add status to Enrollment. Various fixes to Enrollment service/controller.

 

------------------------------------------------------------
revno: 12140
committer: Morten Olav Hansen <mortenoh@xxxxxxxxx>
branch nick: dhis2
timestamp: Wed 2013-09-18 14:19:37 +0200
message:
  Add status to Enrollment. Various fixes to Enrollment service/controller.
added:
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/EnrollmentStatus.java
modified:
  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/enrollment/EnrollmentService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/JacksonEnrollmentService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/DateOfBirth.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/importsummary/ImportSummary.java
  dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramInstanceService.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/EnrollmentController.java


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

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-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	2013-09-18 11:28:35 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/AbstractEnrollmentService.java	2013-09-18 12:19:37 +0000
@@ -30,7 +30,13 @@
 
 import org.hisp.dhis.dxf2.events.person.Person;
 import org.hisp.dhis.dxf2.events.person.PersonService;
+import org.hisp.dhis.dxf2.importsummary.ImportStatus;
+import org.hisp.dhis.dxf2.importsummary.ImportSummary;
+import org.hisp.dhis.i18n.I18nFormat;
+import org.hisp.dhis.i18n.I18nManager;
+import org.hisp.dhis.i18n.I18nManagerException;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.organisationunit.OrganisationUnitService;
 import org.hisp.dhis.patient.Patient;
 import org.hisp.dhis.patient.PatientService;
 import org.hisp.dhis.program.Program;
@@ -60,6 +66,14 @@
     @Autowired
     private PatientService patientService;
 
+    @Autowired
+    private OrganisationUnitService organisationUnitService;
+
+    @Autowired
+    private I18nManager i18nManager;
+
+    private I18nFormat format;
+
     // -------------------------------------------------------------------------
     // READ
     // -------------------------------------------------------------------------
@@ -117,18 +131,6 @@
         return getEnrollments( programInstanceService.getProgramInstances( patient, program ) );
     }
 
-    private Patient getPatient( String person )
-    {
-        Patient patient = patientService.getPatient( person );
-
-        if ( patient == null )
-        {
-            throw new IllegalArgumentException( "Person does not exist." );
-        }
-
-        return patient;
-    }
-
     @Override
     public Enrollments getEnrollments( Collection<ProgramInstance> programInstances )
     {
@@ -156,6 +158,7 @@
         enrollment.setEnrollment( programInstance.getUid() );
         enrollment.setPerson( programInstance.getPatient().getUid() );
         enrollment.setProgram( programInstance.getProgram().getUid() );
+        enrollment.setStatus( EnrollmentStatus.fromInt( programInstance.getStatus() ) );
         enrollment.setDateOfEnrollment( programInstance.getEnrollmentDate() );
         enrollment.setDateOfIncident( programInstance.getDateOfIncident() );
 
@@ -163,6 +166,66 @@
     }
 
     // -------------------------------------------------------------------------
+    // CREATE
+    // -------------------------------------------------------------------------
+
+    @Override
+    public ImportSummary saveEnrollment( Enrollment enrollment )
+    {
+        try
+        {
+            format = i18nManager.getI18nFormat();
+        }
+        catch ( I18nManagerException ex )
+        {
+            return new ImportSummary( ImportStatus.ERROR, ex.getMessage() );
+        }
+
+        Patient patient = getPatient( enrollment.getPerson() );
+        Program program = getProgram( enrollment.getProgram() );
+
+        ProgramInstance programInstance = programInstanceService.enrollPatient( patient, program, enrollment.getDateOfEnrollment(), enrollment.getDateOfIncident(),
+            patient.getOrganisationUnit(), format );
+
+        if ( programInstance == null )
+        {
+            return new ImportSummary( ImportStatus.ERROR, "Could not enroll person " + enrollment.getPerson()
+                + " into program " + enrollment.getProgram() );
+        }
+
+        ImportSummary importSummary = new ImportSummary( ImportStatus.SUCCESS );
+        importSummary.setReference( programInstance.getUid() );
+        importSummary.setDataValueCount( null );
+        importSummary.getImportCount().incrementImported();
+
+        return importSummary;
+    }
+
+    // -------------------------------------------------------------------------
+    // UPDATE
+    // -------------------------------------------------------------------------
+
+    @Override
+    public ImportSummary updateEnrollment( Enrollment enrollment )
+    {
+        return null;
+    }
+
+    // -------------------------------------------------------------------------
+    // DELETE
+    // -------------------------------------------------------------------------
+
+    @Override
+    public void deleteEnrollment( Enrollment enrollment )
+    {
+    }
+
+    @Override
+    public void cancelEnrollment( Enrollment enrollment )
+    {
+    }
+
+    // -------------------------------------------------------------------------
     // HELPERS
     // -------------------------------------------------------------------------
 
@@ -174,4 +237,41 @@
 
         return programs;
     }
+
+    private Patient getPatient( String person )
+    {
+        Patient patient = patientService.getPatient( person );
+
+        if ( patient == null )
+        {
+            throw new IllegalArgumentException( "Person does not exist." );
+        }
+
+        return patient;
+    }
+
+    private Program getProgram( String id )
+    {
+        Program program = programService.getProgram( id );
+
+        if ( program == null )
+        {
+            throw new IllegalArgumentException( "Program does not exist." );
+        }
+
+        return program;
+    }
+
+    private OrganisationUnit getOrganisationUnit( String id )
+    {
+        OrganisationUnit organisationUnit = organisationUnitService.getOrganisationUnit( id );
+
+        if ( organisationUnit == null )
+        {
+            throw new IllegalArgumentException( "OrganisationUnit does not exist." );
+        }
+
+        return organisationUnit;
+    }
+
 }
\ 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	2013-09-18 11:28:35 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/Enrollment.java	2013-09-18 12:19:37 +0000
@@ -47,6 +47,8 @@
 
     private String program;
 
+    private EnrollmentStatus status;
+
     private Date dateOfEnrollment;
 
     private Date dateOfIncident;
@@ -93,6 +95,18 @@
 
     @JsonProperty( required = true )
     @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public EnrollmentStatus getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus( EnrollmentStatus status )
+    {
+        this.status = status;
+    }
+
+    @JsonProperty( required = true )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public Date getDateOfEnrollment()
     {
         return dateOfEnrollment;

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/EnrollmentService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/EnrollmentService.java	2013-09-18 11:28:35 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/EnrollmentService.java	2013-09-18 12:19:37 +0000
@@ -29,11 +29,15 @@
  */
 
 import org.hisp.dhis.dxf2.events.person.Person;
+import org.hisp.dhis.dxf2.importsummary.ImportSummaries;
+import org.hisp.dhis.dxf2.importsummary.ImportSummary;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.patient.Patient;
 import org.hisp.dhis.program.Program;
 import org.hisp.dhis.program.ProgramInstance;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.Collection;
 
 /**
@@ -69,12 +73,27 @@
     // CREATE
     // -------------------------------------------------------------------------
 
+    ImportSummary saveEnrollment( Enrollment enrollment );
+
+    ImportSummaries saveEnrollmentsJson( InputStream inputStream ) throws IOException;
+
+    ImportSummaries saveEnrollmentsXml( InputStream inputStream ) throws IOException;
 
     // -------------------------------------------------------------------------
     // UPDATE
     // -------------------------------------------------------------------------
 
+    ImportSummary updateEnrollment( Enrollment enrollment );
+
+    ImportSummary updateEnrollmentJson( String id, InputStream inputStream ) throws IOException;
+
+    ImportSummary updateEnrollmentXml( String id, InputStream inputStream ) throws IOException;
+
     // -------------------------------------------------------------------------
     // DELETE
     // -------------------------------------------------------------------------
+
+    void deleteEnrollment( Enrollment enrollment );
+
+    void cancelEnrollment( Enrollment enrollment );
 }

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/EnrollmentStatus.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/EnrollmentStatus.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/EnrollmentStatus.java	2013-09-18 12:19:37 +0000
@@ -0,0 +1,62 @@
+package org.hisp.dhis.dxf2.events.enrollment;
+
+/*
+ * Copyright (c) 2004-2013, 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.
+ */
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+public enum EnrollmentStatus
+{
+    ACTIVE( 0 ), COMPLETED( 1 ), CANCELLED( 2 );
+
+    private final int value;
+
+    private EnrollmentStatus( int value )
+    {
+        this.value = value;
+    }
+
+    public int getValue()
+    {
+        return value;
+    }
+
+    public static EnrollmentStatus fromInt( int status )
+    {
+        for ( EnrollmentStatus enrollmentStatus : EnrollmentStatus.values() )
+        {
+            if ( enrollmentStatus.getValue() == status )
+            {
+                return enrollmentStatus;
+            }
+        }
+
+        throw new IllegalArgumentException();
+    }
+}

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/JacksonEnrollmentService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/JacksonEnrollmentService.java	2013-09-17 13:03:51 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/enrollment/JacksonEnrollmentService.java	2013-09-18 12:19:37 +0000
@@ -31,9 +31,13 @@
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+import org.hisp.dhis.dxf2.importsummary.ImportSummaries;
+import org.hisp.dhis.dxf2.importsummary.ImportSummary;
+import org.springframework.util.StreamUtils;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.charset.Charset;
 
 /**
  * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
@@ -47,25 +51,25 @@
     private static ObjectMapper xmlMapper = new XmlMapper();
     private static ObjectMapper jsonMapper = new ObjectMapper();
 
-    @SuppressWarnings( "unchecked" )
+    @SuppressWarnings("unchecked")
     private static <T> T fromXml( InputStream inputStream, Class<?> clazz ) throws IOException
     {
         return (T) xmlMapper.readValue( inputStream, clazz );
     }
 
-    @SuppressWarnings( "unchecked" )
+    @SuppressWarnings("unchecked")
     private static <T> T fromXml( String input, Class<?> clazz ) throws IOException
     {
         return (T) xmlMapper.readValue( input, clazz );
     }
 
-    @SuppressWarnings( "unchecked" )
+    @SuppressWarnings("unchecked")
     private static <T> T fromJson( InputStream inputStream, Class<?> clazz ) throws IOException
     {
         return (T) jsonMapper.readValue( inputStream, clazz );
     }
 
-    @SuppressWarnings( "unchecked" )
+    @SuppressWarnings("unchecked")
     private static <T> T fromJson( String input, Class<?> clazz ) throws IOException
     {
         return (T) jsonMapper.readValue( input, clazz );
@@ -81,4 +85,81 @@
         jsonMapper.configure( DeserializationFeature.WRAP_EXCEPTIONS, true );
     }
 
+    // -------------------------------------------------------------------------
+    // CREATE
+    // -------------------------------------------------------------------------
+
+    @Override
+    public ImportSummaries saveEnrollmentsJson( InputStream inputStream ) throws IOException
+    {
+        ImportSummaries importSummaries = new ImportSummaries();
+        String input = StreamUtils.copyToString( inputStream, Charset.forName( "UTF-8" ) );
+
+        try
+        {
+            Enrollments enrollments = fromJson( input, Enrollments.class );
+
+            for ( Enrollment enrollment : enrollments.getEnrollments() )
+            {
+                enrollment.setEnrollment( null );
+                importSummaries.addImportSummary( saveEnrollment( enrollment ) );
+            }
+        }
+        catch ( Exception ex )
+        {
+            Enrollment enrollment = fromJson( input, Enrollment.class );
+            enrollment.setEnrollment( null );
+            importSummaries.addImportSummary( saveEnrollment( enrollment ) );
+        }
+
+        return importSummaries;
+    }
+
+    @Override
+    public ImportSummaries saveEnrollmentsXml( InputStream inputStream ) throws IOException
+    {
+        ImportSummaries importSummaries = new ImportSummaries();
+        String input = StreamUtils.copyToString( inputStream, Charset.forName( "UTF-8" ) );
+
+        try
+        {
+            Enrollments enrollments = fromXml( input, Enrollments.class );
+
+            for ( Enrollment enrollment : enrollments.getEnrollments() )
+            {
+                enrollment.setEnrollment( null );
+                importSummaries.addImportSummary( saveEnrollment( enrollment ) );
+            }
+        }
+        catch ( Exception ex )
+        {
+            Enrollment enrollment = fromXml( input, Enrollment.class );
+            enrollment.setEnrollment( null );
+            importSummaries.addImportSummary( saveEnrollment( enrollment ) );
+        }
+
+        return importSummaries;
+    }
+
+    // -------------------------------------------------------------------------
+    // UPDATE
+    // -------------------------------------------------------------------------
+
+    @Override
+    public ImportSummary updateEnrollmentJson( String id, InputStream inputStream ) throws IOException
+    {
+        Enrollment enrollment = fromJson( inputStream, Enrollment.class );
+        enrollment.setEnrollment( id );
+
+        return updateEnrollment( enrollment );
+    }
+
+    @Override
+    public ImportSummary updateEnrollmentXml( String id, InputStream inputStream ) throws IOException
+    {
+        Enrollment enrollment = fromXml( inputStream, Enrollment.class );
+        enrollment.setEnrollment( id );
+
+        return updateEnrollment( enrollment );
+    }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/DateOfBirth.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/DateOfBirth.java	2013-09-17 12:15:39 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/person/DateOfBirth.java	2013-09-18 12:19:37 +0000
@@ -83,7 +83,7 @@
     }
 
     @JsonProperty( required = true )
-    @JacksonXmlProperty( isAttribute = true )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public DateOfBirthType getType()
     {
         return type;

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/importsummary/ImportSummary.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/importsummary/ImportSummary.java	2013-09-13 13:27:19 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/importsummary/ImportSummary.java	2013-09-18 12:19:37 +0000
@@ -67,6 +67,11 @@
         this.description = description;
     }
 
+    public ImportSummary( ImportStatus status )
+    {
+        this.status = status;
+    }
+
     @JsonProperty
     @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public ImportStatus getStatus()

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramInstanceService.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramInstanceService.java	2013-09-18 09:50:42 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramInstanceService.java	2013-09-18 12:19:37 +0000
@@ -612,7 +612,7 @@
 
     @Override
     public ProgramInstance enrollPatient( Patient patient, Program program, Date enrollmentDate,
-        Date dateOfIncident, OrganisationUnit orgunit, I18nFormat format )
+        Date dateOfIncident, OrganisationUnit organisationUnit, I18nFormat format )
     {
         if ( enrollmentDate == null )
         {
@@ -656,7 +656,7 @@
             if ( programStage.getAutoGenerateEvent() )
             {
                 ProgramStageInstance programStageInstance = generateEvent( programInstance, programStage,
-                    enrollmentDate, dateOfIncident, orgunit );
+                    enrollmentDate, dateOfIncident, organisationUnit );
                 programStageInstanceService.addProgramStageInstance( programStageInstance );
             }
         }

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/EnrollmentController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/EnrollmentController.java	2013-09-18 09:50:42 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/event/EnrollmentController.java	2013-09-18 12:19:37 +0000
@@ -37,25 +37,33 @@
 import org.hisp.dhis.dxf2.events.enrollment.Enrollments;
 import org.hisp.dhis.dxf2.events.person.Person;
 import org.hisp.dhis.dxf2.events.person.PersonService;
+import org.hisp.dhis.dxf2.importsummary.ImportStatus;
+import org.hisp.dhis.dxf2.importsummary.ImportSummaries;
 import org.hisp.dhis.dxf2.importsummary.ImportSummary;
+import org.hisp.dhis.dxf2.utils.JacksonUtils;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.program.Program;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseStatus;
 
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
 import java.util.Map;
 
 /**
  * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
  */
 @Controller
-@RequestMapping(value = EnrollmentController.RESOURCE_PATH)
+@RequestMapping( value = EnrollmentController.RESOURCE_PATH )
 public class EnrollmentController
 {
     public static final String RESOURCE_PATH = "/enrollments";
@@ -75,9 +83,9 @@
 
     @RequestMapping( value = "", method = RequestMethod.GET )
     public String getEnrollments(
-        @RequestParam(value = "orgUnit", required = false) String orgUnitUid,
-        @RequestParam(value = "program", required = false) String programUid,
-        @RequestParam(value = "person", required = false) String personUid,
+        @RequestParam( value = "orgUnit", required = false ) String orgUnitUid,
+        @RequestParam( value = "program", required = false ) String programUid,
+        @RequestParam( value = "person", required = false ) String personUid,
         @RequestParam Map<String, String> parameters, Model model, HttpServletRequest request ) throws NotFoundException
     {
         WebOptions options = new WebOptions( parameters );
@@ -136,6 +144,90 @@
     }
 
     // -------------------------------------------------------------------------
+    // CREATE
+    // -------------------------------------------------------------------------
+
+    @RequestMapping( value = "", method = RequestMethod.POST, consumes = MediaType.APPLICATION_XML_VALUE )
+    public void postEnrollmentXml( HttpServletRequest request, HttpServletResponse response ) throws IOException
+    {
+        ImportSummaries importSummaries = enrollmentService.saveEnrollmentsXml( request.getInputStream() );
+
+        if ( importSummaries.getImportSummaries().size() > 1 )
+        {
+            response.setStatus( HttpServletResponse.SC_CREATED );
+            JacksonUtils.toXml( response.getOutputStream(), importSummaries );
+        }
+        else
+        {
+            response.setStatus( HttpServletResponse.SC_CREATED );
+            ImportSummary importSummary = importSummaries.getImportSummaries().get( 0 );
+
+            if ( !importSummary.getStatus().equals( ImportStatus.ERROR ) )
+            {
+                response.setHeader( "Location", getResourcePath( request, importSummary ) );
+            }
+
+            JacksonUtils.toXml( response.getOutputStream(), importSummary );
+        }
+    }
+
+    @RequestMapping( value = "", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE )
+    public void postEnrollmentJson( HttpServletRequest request, HttpServletResponse response ) throws IOException
+    {
+        ImportSummaries importSummaries = enrollmentService.saveEnrollmentsJson( request.getInputStream() );
+
+        if ( importSummaries.getImportSummaries().size() > 1 )
+        {
+            response.setStatus( HttpServletResponse.SC_CREATED );
+            JacksonUtils.toJson( response.getOutputStream(), importSummaries );
+        }
+        else
+        {
+            response.setStatus( HttpServletResponse.SC_CREATED );
+            ImportSummary importSummary = importSummaries.getImportSummaries().get( 0 );
+
+            if ( !importSummary.getStatus().equals( ImportStatus.ERROR ) )
+            {
+                response.setHeader( "Location", getResourcePath( request, importSummary ) );
+            }
+
+            JacksonUtils.toJson( response.getOutputStream(), importSummary );
+        }
+    }
+
+    // -------------------------------------------------------------------------
+    // UPDATE
+    // -------------------------------------------------------------------------
+
+    @RequestMapping( value = "/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_XML_VALUE )
+    @ResponseStatus( value = HttpStatus.NO_CONTENT )
+    public void updateEnrollmentXml( @PathVariable String id, HttpServletRequest request, HttpServletResponse response ) throws IOException
+    {
+        ImportSummary importSummary = personService.updatePersonXml( id, request.getInputStream() );
+        JacksonUtils.toXml( response.getOutputStream(), importSummary );
+    }
+
+    @RequestMapping( value = "/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE )
+    @ResponseStatus( value = HttpStatus.NO_CONTENT )
+    public void updateEnrollmentJson( @PathVariable String id, HttpServletRequest request, HttpServletResponse response ) throws IOException
+    {
+        ImportSummary importSummary = enrollmentService.updateEnrollmentJson( id, request.getInputStream() );
+        JacksonUtils.toJson( response.getOutputStream(), importSummary );
+    }
+
+    // -------------------------------------------------------------------------
+    // DELETE
+    // -------------------------------------------------------------------------
+
+    @RequestMapping( value = "/{id}", method = RequestMethod.DELETE )
+    @ResponseStatus( HttpStatus.NO_CONTENT )
+    public void deleteEnrollment( @PathVariable String id, @RequestParam Map<String, String> parameters, Model model ) throws NotFoundException
+    {
+        Enrollment enrollment = getEnrollment( id );
+        enrollmentService.cancelEnrollment( enrollment );
+    }
+
+    // -------------------------------------------------------------------------
     // HELPERS
     // -------------------------------------------------------------------------