Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion DataQualityExternalModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,12 @@ public function checkApiToken() {

$post = $data->getRequestVars();
}
}

public function getProcessJsonDownURL() {
return $this->getUrl("exportJsonFile.php", false, false);
}

public function getProcessJsonUpURL() {
return $this->getUrl("importJsonFile.php", false, false);
}
}
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,9 @@ The data quality import only allows the import of new resolutions. A new status

Input for data quality import is identical to the data quality export's output. Duplicate resolutions will not be imported (those with the same ts and username as existing resolutions).

Output for data quality import is a json array of [res_ids].
Output for data quality import is a json array of [res_ids].

## Syncing Data Resolutions between projects
When importing data resolutions using the index.php plugin, you will have the option to "Ignore PID and Usernames?"

This option should be used only in situations where you are syncing resolutions between projects that have the same data dictionaries and data, but differing users and PIDs.
15 changes: 13 additions & 2 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,23 @@
"institution": "Vanderbilt University Medical Center"
}
],

"permissions": [
],

"no-auth-pages":["import","export"],

"project-settings": [
]
],

"links": {
"project": [
{
"name": "Data Quality API",
"icon": "arrow_circle_double_135",
"url": "index.php",
"show-header-and-footer": true
}
]
}
}
136 changes: 136 additions & 0 deletions exportJsonFile.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<?php
global $post;

$project_id = @$_POST["pid"];

if($project_id == "") die("Invalid request, pid missing");

# Add SQL to filter results by a single record
$recordSql = "";
if($post['record'] != "") {
if(is_array($post['record'])) {
## Clean API variables individually
$recordList = [];
foreach($post['record'] as $newRecord) {
$recordList[] = db_escape($newRecord);
}
$recordSql = " AND s.record IN ('".implode("','",$recordList)."')";
}
else {
$recordSql = " AND s.record = '".db_escape($post['record'])."'";
}
}

# Add SQL to filter results by a single user
$userSql = "";
if($post['user'] != "") {
$user_id = User::getUIIDByUsername($post['user']);
if(!empty($user_id) && is_numeric($user_id)) {
$userSql = " AND s.assigned_user_id = '" . db_escape($user_id) . "'";
}
}

# Add SQL to filter results by a single status
$statusSql = "";
if($post['status'] != "") {
if($post['status'] == "OPEN") {
$statusSql = " AND (s.query_status = '" . db_escape($post['status']) . "' OR s.query_status IS NULL) ";
} else {
$statusSql = " AND s.query_status = '" . db_escape($post['status']) . "'";
}
}

## Get list of status IDs associated with this project/record(s)
$sql1 = "
SELECT s.*, g.value as group_id
FROM redcap_data_quality_status s

-- join to metadata to exclude fields that no longer exist (like REDCap does programmatically)
JOIN redcap_metadata m
ON m.project_id = $project_id
AND s.field_name = m.field_name

-- this joins one row per event & instance, requiring the GROUP BY below
LEFT JOIN redcap_data g
ON s.record = g.record
AND g.project_id = $project_id
AND g.field_name = '__GROUPID__'

WHERE s.project_id = ".$project_id.$recordSql.$userSql.$statusSql."
GROUP BY status_id
";

$q = db_query($sql1);

if($e = db_error()) {
throw new Exception("Database error while pulling data quality status");
}

$statusList = array();
$userIdConversion = array(NULL => NULL);

## Read all the rows from the table ino the $statusList variable
while($row = db_fetch_assoc($q)) {
$userId = $row['assigned_user_id'];
unset($row['assigned_user_id']);

## Cache User ID to username conversion to reduce DB calls
if(!array_key_exists($userId,$userIdConversion)) {
$userIdConversion[$userId] = User::getUserInfoByUiid($userId)['username'];
}
$row['assigned_username'] = $userIdConversion[$userId];
$statusList[$row['status_id']] = $row;
}

if(count($statusList) > 0) {
$sql = "SELECT r.*
FROM redcap_data_quality_resolutions r
WHERE r.status_id IN ('".implode("','",array_keys($statusList))."')";

$q = db_query($sql);

if($e = db_error()) {
throw new Exception("Database error while pulling data quality resolutions");
}

while($row = db_fetch_assoc($q)) {
if(!array_key_exists("resolutions",$statusList[$row['status_id']])) {
$statusList[$row['status_id']]["resolutions"] = array();
}
$userId = $row['user_id'];
unset($row['user_id']);

## Cache User ID to username conversion to reduce DB calls
if(!array_key_exists($userId,$userIdConversion)) {
$userIdConversion[$userId] = User::getUserInfoByUiid($userId)['username'];
}
$row['username'] = $userIdConversion[$userId];
$statusList[$row['status_id']]["resolutions"][$row["res_id"]] = $row;
}
}

// $uid = User::getUIIDByUsername($post['user']);

// $retData = array(
// 'uid' => $uid,
// 'user' => $post['user'],
// 'sql' => $sql
// );

// $content = json_encode($sql1);
$content = json_encode($statusList);

# Export to a JSON file
$datestamp = new DateTime();
$filename=$project_id."-data_quality-".$datestamp->format("Y-m-d").".json";

// $fp = fopen($filename, 'w');
// fwrite($fp, $content);
// fclose($fp);

header("Content-type: application/json");
header("Content-Disposition: attachment; filename=".$filename);
header("Pragma: no-cache");
header("Expires: 0");

echo($content);
Loading