Building customized reports inside modules (For Developers)

Reporting API

Reporting API has been designed what we consider to be the basis for all of the APIs needed for the reporting. We feel very confident that the classes and interfaces designed will allow you to use and extend the API to:

  • Define new cohort queries to allow users to calculate a custom metric that is specific to your organization.
  • Define new data set definitions to expose data sets that are important to your users.
  • Define new custom data set definitions that can be used in any implementation.
  • Define a custom report based on your own data set definition.
  • Build new reporting tools and user interfaces (e.g. a custom Reporting Dashboard for clinicians or an interactive data quality tool for data managers).
  • Render reports in a standard format (e.g. SDMX-HD).
  • Render reports in a proprietary format (e.g. .docx).
  • Define custom logic rules to be used in indicators and cohort queries.
  • Define new data quality rules to allow data managers to identify problems areas within your form entry process.

Developing a Customised Reporting Module

Reports can be created as a module that works in conjunction with the reporting module. The advantage of this method is the portability of the report. It can be shared among different instances of OpenMRS without having to be recreated in the UI.

Save a report definition

In general you will add a class which will save your report definition to the database.

MyReportSetup.java
// Tested with reporting module 0.6.3
PeriodIndicatorReportDefinition rd = new PeriodIndicatorReportDefinition();
rd.setName("myReport");
rd.setupDataSetDefinition();

// add cohort queries, indicators, etc. here

ReportDefinitionService rds = (ReportDefinitionService) Context.getService(ReportDefinitionService.class);
rds.saveDefinition(rd);

Create a custom web report renderer

You can add a custom web report renderer to your report by implementing the following components. The given code is not complete but it should allow you to implement your custom web report renderer.

  1. Implement WebReportRenderer interface

    MyReportWebRenderer.java
    // Tested with reporting module 0.6.3
    public class MyReportWebRenderer extends IndicatorReportWebRenderer implements WebReportRenderer {
    	
       /**
         * @see org.openmrs.report.ReportRenderer#getLabel()
         */
    	@Override
        public String getLabel() {
        	return "Web Report";
        }
    	
    	
    	/**
    	 * @see org.openmrs.module.reporting.web.renderers.WebReportRenderer#getLinkUrl(org.openmrs.module.reporting.report.definition.ReportDefinition)
    	 */
    	@Override
    	public String getLinkUrl(ReportDefinition arg0) {
    		return "module/myreports/render.form";
    	}
    	
    	/**
    	 * @see org.openmrs.report.ReportRenderer#getRenderingModes(org.openmrs.report.ReportDefinition)
    	 */
    	@Override
    	public Collection<RenderingMode> getRenderingModes(ReportDefinition definition) {
    		List<RenderingMode> ret = new ArrayList<RenderingMode>();
    		for (Map.Entry<String, Mapped<? extends DataSetDefinition>> e : definition.getDataSetDefinitions().entrySet()) {
    			String name = e.getKey();
    			DataSetDefinition def = e.getValue().getParameterizable();
    	    	if ("myReport Data Set".equals(def.getName())) {
    				ret.add(new RenderingMode(this, this.getLabel() , name, Integer.MAX_VALUE - 10));
    	    	}
    		}
    		return ret;
    	}
    	
    }
    
  2. Save WebReportRenderer

    MyReportSetup.java
        	final ReportDesign design = new ReportDesign();
        	design.setName(name);
        	design.setReportDefinition(rd);
        	design.setRendererType(MyReportWebRenderer.class);
        	
        	ReportService rs = Context.getService(ReportService.class);
        	rs.saveReportDesign(design);
    
  3. To display results add a Controller and a JSP

    RenderMyReportController.java
    // Tested with reporting module 0.6.3
    @Controller
    public class RenderMyReportController {
    	
    	@RequestMapping("/module/myreports/render")
    	public String showReport(Model model, HttpSession session) {
    		
    		String renderArg = (String) session.getAttribute(ReportingConstants.OPENMRS_REPORT_ARGUMENT);
    		ReportData data = null;
    		try {
    			data = (ReportData) session.getAttribute(ReportingConstants.OPENMRS_REPORT_DATA);
    		}
    		catch (ClassCastException ex) {
    			// pass
    		}
    		if (data == null)
    			return "redirect:../reporting/dashboard/index.form";
    		
    		return null;
    	}
    
    render.jsp
    <%--
      This page assumes a ReportData object in the session as the attribute '__openmrs_report_data'
    --%>
    
    <c:set var="dataSetMaps" value="${__openmrs_report_data.dataSets}" />
    <c:set var="mapDataSet" value="${dataSetMaps['defaultDataSet'].data}"/>
    
    <openmrs:portlet url="currentReportHeader" moduleId="reporting" parameters="showDiscardButton=true"/>
    
    <div>
    Indicator value: ${mapDataSet.columnValuesByKey["myKey"].value} </a>
    </div>
    

Getting Started with the basicreportmodule

IMPORTANT-- This module does not exist as of .  For now, see the following modules for ideas:

rwandareports

pihmalawi

mdrtb