mirror of
https://github.com/pcvolkmer/etl-processor.git
synced 2025-04-19 17:26:51 +00:00
Enable patient data deletion
This commit is contained in:
parent
aed5f15d2d
commit
9af0e159b0
@ -24,5 +24,7 @@ enum class RequestStatus(val value: String) {
|
|||||||
WARNING("warning"),
|
WARNING("warning"),
|
||||||
ERROR("error"),
|
ERROR("error"),
|
||||||
UNKNOWN("unknown"),
|
UNKNOWN("unknown"),
|
||||||
DUPLICATION("duplication")
|
DUPLICATION("duplication"),
|
||||||
|
DELETE_SUCCESS("delete_success"),
|
||||||
|
DELETE_ERROR("delete_error")
|
||||||
}
|
}
|
@ -22,11 +22,15 @@ package dev.dnpm.etl.processor.output
|
|||||||
import de.ukw.ccc.bwhc.dto.MtbFile
|
import de.ukw.ccc.bwhc.dto.MtbFile
|
||||||
|
|
||||||
interface MtbFileSender {
|
interface MtbFileSender {
|
||||||
fun send(request: Request): Response
|
fun send(request: MtbFileRequest): Response
|
||||||
|
|
||||||
|
fun send(request: DeleteRequest): Response
|
||||||
|
|
||||||
data class Response(val status: ResponseStatus, val reason: String = "")
|
data class Response(val status: ResponseStatus, val reason: String = "")
|
||||||
|
|
||||||
data class Request(val requestId: String, val mtbFile: MtbFile)
|
data class MtbFileRequest(val requestId: String, val mtbFile: MtbFile)
|
||||||
|
|
||||||
|
data class DeleteRequest(val requestId: String, val patientId: String)
|
||||||
|
|
||||||
enum class ResponseStatus {
|
enum class ResponseStatus {
|
||||||
SUCCESS,
|
SUCCESS,
|
||||||
|
@ -28,7 +28,7 @@ class PseudonymizeService(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
fun pseudonymize(mtbFile: MtbFile): MtbFile {
|
fun pseudonymize(mtbFile: MtbFile): MtbFile {
|
||||||
val patientPseudonym = "${configProperties.prefix}_${generator.generate(mtbFile.patient.id)}"
|
val patientPseudonym = patientPseudonym(mtbFile.patient.id)
|
||||||
|
|
||||||
mtbFile.episode.patient = patientPseudonym
|
mtbFile.episode.patient = patientPseudonym
|
||||||
mtbFile.carePlans.forEach { it.patient = patientPseudonym }
|
mtbFile.carePlans.forEach { it.patient = patientPseudonym }
|
||||||
@ -57,4 +57,8 @@ class PseudonymizeService(
|
|||||||
return mtbFile
|
return mtbFile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun patientPseudonym(patientId: String): String {
|
||||||
|
return "${configProperties.prefix}_${generator.generate(patientId)}"
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -31,6 +31,7 @@ import org.apache.commons.codec.binary.Base32
|
|||||||
import org.apache.commons.codec.digest.DigestUtils
|
import org.apache.commons.codec.digest.DigestUtils
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.http.ResponseEntity
|
import org.springframework.http.ResponseEntity
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable
|
||||||
import org.springframework.web.bind.annotation.PostMapping
|
import org.springframework.web.bind.annotation.PostMapping
|
||||||
import org.springframework.web.bind.annotation.RequestBody
|
import org.springframework.web.bind.annotation.RequestBody
|
||||||
import org.springframework.web.bind.annotation.RestController
|
import org.springframework.web.bind.annotation.RestController
|
||||||
@ -71,7 +72,7 @@ class MtbFileController(
|
|||||||
return ResponseEntity.noContent().build()
|
return ResponseEntity.noContent().build()
|
||||||
}
|
}
|
||||||
|
|
||||||
val request = MtbFileSender.Request(UUID.randomUUID().toString(), pseudonymized)
|
val request = MtbFileSender.MtbFileRequest(UUID.randomUUID().toString(), pseudonymized)
|
||||||
|
|
||||||
val responses = senders.map {
|
val responses = senders.map {
|
||||||
val responseStatus = it.send(request)
|
val responseStatus = it.send(request)
|
||||||
@ -128,8 +129,63 @@ class MtbFileController(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping(path = ["/mtbfile/{patientId}"])
|
||||||
|
fun deleteData(@PathVariable patientId: String): ResponseEntity<Void> {
|
||||||
|
val requestId = UUID.randomUUID().toString()
|
||||||
|
|
||||||
|
try {
|
||||||
|
val patientPseudonym = pseudonymizeService.patientPseudonym(patientId)
|
||||||
|
|
||||||
|
val responses = senders.map {
|
||||||
|
it.send(MtbFileSender.DeleteRequest(requestId, patientPseudonym))
|
||||||
|
}
|
||||||
|
|
||||||
|
val requestStatus = if (responses.map { it.status }.contains(MtbFileSender.ResponseStatus.ERROR)) {
|
||||||
|
RequestStatus.DELETE_ERROR
|
||||||
|
} else if (responses.map { it.status }.contains(MtbFileSender.ResponseStatus.SUCCESS)) {
|
||||||
|
RequestStatus.DELETE_SUCCESS
|
||||||
|
} else {
|
||||||
|
RequestStatus.UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
requestRepository.save(
|
||||||
|
Request(
|
||||||
|
uuid = requestId,
|
||||||
|
patientId = patientPseudonym,
|
||||||
|
pid = patientId,
|
||||||
|
fingerprint = fingerprint(patientPseudonym),
|
||||||
|
status = requestStatus,
|
||||||
|
report = when (requestStatus) {
|
||||||
|
RequestStatus.DELETE_ERROR -> Report("Fehler bei der Datenübertragung oder Inhalt nicht verarbeitbar")
|
||||||
|
RequestStatus.UNKNOWN -> Report("Keine Informationen")
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return ResponseEntity.unprocessableEntity().build()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
requestRepository.save(
|
||||||
|
Request(
|
||||||
|
uuid = requestId,
|
||||||
|
patientId = "???",
|
||||||
|
pid = patientId,
|
||||||
|
fingerprint = "",
|
||||||
|
status = RequestStatus.DELETE_ERROR,
|
||||||
|
report = Report("Fehler bei der Pseudonymisierung")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return ResponseEntity.noContent().build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun fingerprint(mtbFile: MtbFile): String {
|
private fun fingerprint(mtbFile: MtbFile): String {
|
||||||
return Base32().encodeAsString(DigestUtils.sha256(objectMapper.writeValueAsString(mtbFile)))
|
return fingerprint(objectMapper.writeValueAsString(mtbFile))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fingerprint(s: String): String {
|
||||||
|
return Base32().encodeAsString(DigestUtils.sha256(s))
|
||||||
.replace("=", "")
|
.replace("=", "")
|
||||||
.lowercase()
|
.lowercase()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user