Skip to content

Commit 25f6a4a

Browse files
authored
O3-5229: Should be able to load system tasks and create tasks from system tasks (#310)
1 parent 80d2634 commit 25f6a4a

16 files changed

Lines changed: 826 additions & 9 deletions

File tree

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ configuration/
9393
├── providerroles/
9494
├── queues/
9595
├── relationshiptypes/
96-
└── roles/
96+
├── roles/
97+
└── systemtasks/
9798

9899
```
99100
Each domain-specific subfolder contains OpenMRS metadata configuration files that pertains to the domain.
@@ -127,6 +128,7 @@ This is the list of currently supported domains in their loading order:
127128
1. [Global Properties (XML files)](readme/globalproperties.md)
128129
1. [Attribute Types (CSV files)](readme/atttypes.md)
129130
1. [Provider Roles (CSV files)](readme/providerroles.md)
131+
1. [System Tasks (CSV files)](readme/systemtasks.md)
130132
1. [Locations (CSV files)](readme/loc.md)
131133
1. [Location Tag Maps (CSV files)](readme/loctagmaps.md)
132134
1. [Address Hierarchy (XML, CSV, .properties files)](readme/addresshierarchy.md)
@@ -186,6 +188,7 @@ mvn clean package
186188
* Metadata Sharing 1.2.2 (*compatible*)
187189
* Metadata Mapping 1.3.4 (*compatible*)
188190
* Open Concept Lab 1.2.9 (*compatible*)
191+
* Tasks 1.0.0 (*compatible*)
189192

190193
### Test your OpenMRS configs
191194
See the [Initializer Validator README page](readme/validator.md).
@@ -218,6 +221,7 @@ See the [documentation on Initializer's logging properties](readme/rtprops.md#lo
218221
#### Version 2.11.0
219222
* Support for 'billing' (billableservices, paymentmodes, cashpoints) for Billing V2
220223
* Removed support for Billing V1 (1.x) versions
224+
* Support for system tasks with openmrs-module-tasks
221225

222226
#### Version 2.10.0
223227
* Support enhanced methods for loading htmlforms when running htmlformentry 5.5.0+

api-2.8/pom.xml

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>initializer</artifactId>
7+
<groupId>org.openmrs.module</groupId>
8+
<version>2.11.0-SNAPSHOT</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>initializer-api-2.8</artifactId>
13+
<packaging>jar</packaging>
14+
<name>Initializer API 2.8</name>
15+
<description>API 2.8 project for Initializer</description>
16+
17+
<properties>
18+
<openmrsPlatformVersion>${openmrsVersion2.8}</openmrsPlatformVersion>
19+
</properties>
20+
21+
<dependencies>
22+
<dependency>
23+
<groupId>org.openmrs.test</groupId>
24+
<artifactId>openmrs-test</artifactId>
25+
<type>pom</type>
26+
<version>${openmrsPlatformVersion}</version>
27+
<scope>test</scope>
28+
<exclusions>
29+
<exclusion>
30+
<groupId>org.powermock</groupId>
31+
<artifactId>powermock-api-mockito2</artifactId>
32+
</exclusion>
33+
</exclusions>
34+
</dependency>
35+
36+
<dependency>
37+
<groupId>${project.parent.groupId}</groupId>
38+
<artifactId>${project.parent.artifactId}-api</artifactId>
39+
<version>${project.parent.version}</version>
40+
<scope>provided</scope>
41+
</dependency>
42+
43+
<dependency>
44+
<groupId>${project.parent.groupId}</groupId>
45+
<artifactId>${project.parent.artifactId}-api</artifactId>
46+
<version>${project.parent.version}</version>
47+
<scope>test</scope>
48+
<type>test-jar</type>
49+
</dependency>
50+
51+
<dependency>
52+
<groupId>${project.parent.groupId}</groupId>
53+
<artifactId>${project.parent.artifactId}-api-2.2</artifactId>
54+
<version>${project.parent.version}</version>
55+
<scope>provided</scope>
56+
</dependency>
57+
58+
<dependency>
59+
<groupId>${project.parent.groupId}</groupId>
60+
<artifactId>${project.parent.artifactId}-api-2.2</artifactId>
61+
<version>${project.parent.version}</version>
62+
<scope>test</scope>
63+
<type>test-jar</type>
64+
</dependency>
65+
66+
<dependency>
67+
<groupId>org.openmrs.module</groupId>
68+
<artifactId>tasks-api</artifactId>
69+
<version>${tasksVersion}</version>
70+
<scope>provided</scope>
71+
</dependency>
72+
73+
74+
</dependencies>
75+
76+
<build>
77+
<plugins>
78+
<plugin>
79+
<groupId>org.apache.maven.plugins</groupId>
80+
<artifactId>maven-surefire-plugin</artifactId>
81+
<configuration>
82+
<classpathDependencyExcludes>
83+
<!-- Exclude htmlformentry - its moduleApplicationContext.xml has velocity placeholders
84+
that OpenMRS 2.8's PropertySourcesPlaceholderConfigurer tries to resolve -->
85+
<classpathDependencyExclude>org.openmrs.module:htmlformentry-api</classpathDependencyExclude>
86+
<!-- Exclude reporting - CGLIB issues with SerializedDefinitionServiceImpl -->
87+
<classpathDependencyExclude>org.openmrs.module:reporting-api</classpathDependencyExclude>
88+
<classpathDependencyExclude>org.openmrs.module:reporting-api-2.0</classpathDependencyExclude>
89+
90+
</classpathDependencyExcludes>
91+
</configuration>
92+
</plugin>
93+
</plugins>
94+
</build>
95+
</project>
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* This Source Code Form is subject to the terms of the Mozilla Public License,
3+
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
4+
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5+
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6+
*
7+
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8+
* graphic logo is a trademark of OpenMRS Inc.
9+
*/
10+
package org.openmrs.module.initializer.api.systemtasks;
11+
12+
import org.apache.commons.lang3.StringUtils;
13+
import org.openmrs.annotation.OpenmrsProfile;
14+
import org.openmrs.module.initializer.Domain;
15+
import org.openmrs.module.initializer.api.BaseLineProcessor;
16+
import org.openmrs.module.initializer.api.CsvLine;
17+
import org.openmrs.module.initializer.api.CsvParser;
18+
import org.openmrs.module.tasks.SystemTask;
19+
import org.openmrs.module.tasks.api.TasksService;
20+
import org.springframework.beans.factory.annotation.Autowired;
21+
import org.springframework.beans.factory.annotation.Qualifier;
22+
23+
/**
24+
* CSV parser for SystemTask entities. Handles bootstrapping (finding or creating) and saving
25+
* SystemTask instances.
26+
*/
27+
@OpenmrsProfile(modules = { "tasks:*" })
28+
public class SystemTasksCsvParser extends CsvParser<SystemTask, BaseLineProcessor<SystemTask>> {
29+
30+
private TasksService tasksService;
31+
32+
@Autowired
33+
public SystemTasksCsvParser(@Qualifier("tasks.TasksService") TasksService tasksService,
34+
SystemTasksLineProcessor processor) {
35+
super(processor);
36+
this.tasksService = tasksService;
37+
}
38+
39+
@Override
40+
public Domain getDomain() {
41+
return Domain.SYSTEM_TASKS;
42+
}
43+
44+
@Override
45+
public SystemTask bootstrap(CsvLine line) throws IllegalArgumentException {
46+
String uuid = line.getUuid();
47+
if (StringUtils.isEmpty(uuid)) {
48+
throw new IllegalArgumentException("uuid is required for system tasks");
49+
}
50+
51+
SystemTask systemTask = tasksService.getSystemTaskByUuid(uuid);
52+
if (systemTask == null) {
53+
systemTask = new SystemTask();
54+
systemTask.setUuid(uuid);
55+
}
56+
return systemTask;
57+
}
58+
59+
@Override
60+
public SystemTask save(SystemTask instance) {
61+
return tasksService.saveSystemTask(instance);
62+
}
63+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/**
2+
* This Source Code Form is subject to the terms of the Mozilla Public License,
3+
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
4+
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5+
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6+
*
7+
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8+
* graphic logo is a trademark of OpenMRS Inc.
9+
*/
10+
package org.openmrs.module.initializer.api.systemtasks;
11+
12+
import org.apache.commons.lang3.StringUtils;
13+
import org.openmrs.annotation.OpenmrsProfile;
14+
import org.openmrs.api.context.Context;
15+
import org.openmrs.module.initializer.api.BaseLineProcessor;
16+
import org.openmrs.module.initializer.api.CsvLine;
17+
import org.openmrs.module.tasks.Priority;
18+
import org.openmrs.module.tasks.SystemTask;
19+
import org.slf4j.Logger;
20+
import org.slf4j.LoggerFactory;
21+
import org.springframework.stereotype.Component;
22+
23+
/**
24+
* Line processor for SystemTask CSV files. Handles field mapping from CSV columns to SystemTask
25+
* entity properties.
26+
*/
27+
@Component
28+
@OpenmrsProfile(modules = { "tasks:*" })
29+
public class SystemTasksLineProcessor extends BaseLineProcessor<SystemTask> {
30+
31+
private static final Logger log = LoggerFactory.getLogger(SystemTasksLineProcessor.class);
32+
33+
public static final String HEADER_TITLE = "title";
34+
35+
public static final String HEADER_PRIORITY = "priority";
36+
37+
public static final String HEADER_DEFAULT_ASSIGNEE_ROLE = "default assignee role";
38+
39+
public static final String HEADER_RATIONALE = "rationale";
40+
41+
public SystemTasksLineProcessor() {
42+
}
43+
44+
@Override
45+
public SystemTask fill(SystemTask systemTask, CsvLine line) throws IllegalArgumentException {
46+
systemTask.setName(line.getName(true)); // Required - uses HEADER_NAME from base class
47+
systemTask.setTitle(line.get(HEADER_TITLE, true)); // Required
48+
systemTask.setDescription(line.get(HEADER_DESC)); // Uses HEADER_DESC from base class
49+
systemTask.setRationale(line.get(HEADER_RATIONALE));
50+
51+
String priorityStr = line.get(HEADER_PRIORITY);
52+
if (StringUtils.isNotBlank(priorityStr)) {
53+
try {
54+
systemTask.setPriority(Priority.valueOf(priorityStr.toUpperCase()));
55+
}
56+
catch (IllegalArgumentException e) {
57+
throw new IllegalArgumentException(
58+
"Invalid priority value: " + priorityStr + ". Must be one of: HIGH, MEDIUM, LOW");
59+
}
60+
}
61+
62+
String assigneeRole = line.get(HEADER_DEFAULT_ASSIGNEE_ROLE);
63+
if (StringUtils.isNotBlank(assigneeRole)) {
64+
Integer roleId = resolveProviderRoleId(assigneeRole);
65+
systemTask.setDefaultAssigneeProviderRoleId(roleId);
66+
}
67+
68+
return systemTask;
69+
}
70+
71+
/**
72+
* Resolves a provider role ID from either a UUID or a name. Uses reflection to avoid hard
73+
* dependency on providermanagement module.
74+
*
75+
* @param roleReference the UUID or name of the provider role
76+
* @return the provider role ID, or null if providermanagement is not available
77+
* @throws IllegalArgumentException if the provider role cannot be found
78+
*/
79+
private Integer resolveProviderRoleId(String roleReference) {
80+
try {
81+
// Try to get ProviderManagementService via reflection
82+
Class<?> serviceClass = Context.loadClass("org.openmrs.module.providermanagement.api.ProviderManagementService");
83+
Object service = Context.getService(serviceClass);
84+
85+
if (service == null) {
86+
log.warn("ProviderManagementService not available. Cannot resolve provider role: {}", roleReference);
87+
return null;
88+
}
89+
90+
// Check if it looks like a UUID (contains hyphens and is 36 characters)
91+
if (roleReference.contains("-") && roleReference.length() == 36) {
92+
java.lang.reflect.Method getByUuid = serviceClass.getMethod("getProviderRoleByUuid", String.class);
93+
Object role = getByUuid.invoke(service, roleReference);
94+
if (role != null) {
95+
java.lang.reflect.Method getId = role.getClass().getMethod("getProviderRoleId");
96+
return (Integer) getId.invoke(role);
97+
}
98+
}
99+
100+
// Try to find by name
101+
java.lang.reflect.Method getAllRoles = serviceClass.getMethod("getAllProviderRoles", boolean.class);
102+
@SuppressWarnings("unchecked")
103+
java.util.List<?> allRoles = (java.util.List<?>) getAllRoles.invoke(service, false);
104+
105+
for (Object role : allRoles) {
106+
java.lang.reflect.Method getName = role.getClass().getMethod("getName");
107+
String roleName = (String) getName.invoke(role);
108+
if (roleName != null && roleName.equalsIgnoreCase(roleReference)) {
109+
java.lang.reflect.Method getId = role.getClass().getMethod("getProviderRoleId");
110+
return (Integer) getId.invoke(role);
111+
}
112+
}
113+
114+
throw new IllegalArgumentException("Provider role not found: " + roleReference);
115+
}
116+
catch (ClassNotFoundException e) {
117+
log.warn("providermanagement module not available. Cannot resolve provider role: {}", roleReference);
118+
return null;
119+
}
120+
catch (IllegalArgumentException e) {
121+
throw e;
122+
}
123+
catch (Exception e) {
124+
log.error("Error resolving provider role: {}", roleReference, e);
125+
return null;
126+
}
127+
}
128+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* This Source Code Form is subject to the terms of the Mozilla Public License,
3+
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
4+
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5+
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6+
*
7+
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8+
* graphic logo is a trademark of OpenMRS Inc.
9+
*/
10+
package org.openmrs.module.initializer.api.systemtasks;
11+
12+
import org.openmrs.annotation.OpenmrsProfile;
13+
import org.openmrs.module.initializer.api.loaders.BaseCsvLoader;
14+
import org.openmrs.module.tasks.SystemTask;
15+
import org.springframework.beans.factory.annotation.Autowired;
16+
17+
/**
18+
* Loader for SystemTask CSV files. Loads system task templates from the configuration/systemtasks/
19+
* directory.
20+
*/
21+
@OpenmrsProfile(modules = { "tasks:*" })
22+
public class SystemTasksLoader extends BaseCsvLoader<SystemTask, SystemTasksCsvParser> {
23+
24+
@Autowired
25+
public void setParser(SystemTasksCsvParser parser) {
26+
this.parser = parser;
27+
}
28+
}

0 commit comments

Comments
 (0)