Files
d.velop/Hermes/CMC/DeleteTermsContractsCaseManager.groovy
2025-06-02 17:10:23 +02:00

353 lines
18 KiB
Groovy

import com.dvelop.d3.server.core.D3Interface
import com.dvelop.d3.server.exceptions.D3Exception
import com.google.gson.Gson
import groovy.json.JsonSlurper
import groovy.transform.Field
import org.apache.http.HttpEntity
import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpDelete
import org.apache.http.client.methods.HttpGet
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.util.EntityUtils
import java.nio.charset.StandardCharsets
/*
* Dieses Skript loescht alle Fristen und Aufgaben fuer einen bestimmten Vertrag aus dem DBS Case Manager Contract.
*
* Erstellung: 12.2024 d.velop/mtiel
* Optimierung: 05.2025
*/
// Start of script
D3Interface d3 = getProperty("d3") as D3Interface
def scriptName = getClass().getName()
d3.log.info("groovyhook - START Script ${scriptName}")
// Konfiguration
def batchSize = 100 // Größe der Batches für SQL-Abfrage und Verarbeitung
def ddfIntContractNo = 11 // DB-Position der Eigenschaft interne Vertragsnummer
def onlyTerms = false // Wenn nur die Fristen geloescht werden sollen, dann true setzen
def onlyTasks = false // Wenn nur die Aufgaben geloescht werden sollen, dann true setzen
def logDirectory = new File("E:\\d3work\\LOGS\\LOG_$scriptName") // Bitte hier den Pfad zum Logverzeichnis eintragen
@Field String baseUri = "https://d3dev.int.hlg.de" // Bitte hier die Basis URL eintragen
@Field String apiKey = "OJRD7qrEhuoIzM5Pt6M59qApakhyNrA/8My81PPx0/ULs+IisvBdZC6GnhcGTzKRwf4ndOtcsQmNby8YPa+D+mfUFsJGjkEsqhLX3h0N8sg=&_z_A0V5ayCRMk4iQs2RWKEDd9HrFriKdSm-G67jqTxNwqW1jZf2OP2l5b7LkBOKnISHL4YtCPCOz81OVhQgE0TQsWylfWnv1"
// Bitte in der oberen Zeile den API Key fuer den User (wie d3ddecsTaskAPIKey) zum Suchen und Loeschen von Aufgaben eintragen
// Ende Konfiguration
def today = new Date()
def formattedDate = today.format("yyyyMMdd")
if (!logDirectory.exists()) {
logDirectory.mkdir()
}
@Field StringBuilder logBuilder = new StringBuilder()
def logFile = new File(logDirectory.path + "\\${formattedDate}_${System.currentTimeMillis()}_${scriptName}.txt")
logBuilder.append("Info:\t$scriptName - Logfile" + System.getProperty("line.separator"))
def offset = 0 // Offset für die SQL-Abfrage (zur Batch-Verarbeitung)
// Schleife zur Verarbeitung der SQL-Abfrage in Batches
while (true) {
def internalContractNumbers = d3.sql.executeAndGet("""
WITH Vertragsnummern AS (
SELECT DISTINCT t.object_id AS intContractNo
FROM terms_term t
WHERE NOT EXISTS (
SELECT 1 FROM firmen_spezifisch f WHERE f.dok_dat_feld_$ddfIntContractNo = t.object_id
)
UNION ALL
SELECT DISTINCT d.internal_contract_number AS intContractNo
FROM dbsCase_activity d
WHERE NOT EXISTS (
SELECT 1 FROM firmen_spezifisch f WHERE f.dok_dat_feld_$ddfIntContractNo = d.internal_contract_number
)
)
SELECT DISTINCT intContractNo
FROM Vertragsnummern
ORDER BY intContractNo
OFFSET ? ROWS FETCH NEXT ? ROWS ONLY
""", [offset, batchSize])
if (internalContractNumbers?.isEmpty()) {
break // Keine weiteren Daten vorhanden, Schleife beenden
}
internalContractNumbers?.each {
def internalContractNo = it.intContractNo
//Loeschen der Fristen fuer die Vertragsnummer
if (!onlyTasks) {
d3.log.info("groovyhook - Es sollen die Fristen fuer den Vertrag ${internalContractNo} geloescht werden!")
logBuilder.append("Info:\tEs sollen die Fristen fuer den Vertrag ${internalContractNo} geloescht werden!" + System.getProperty("line.separator"))
def termIds = d3.sql.executeAndGet("SELECT DISTINCT id FROM terms_term WHERE object_id = ?", [internalContractNo])
if (!termIds || termIds.isEmpty()) {
d3.log.info("groovyhook - Keine Fristen fuer den Vertrag ${internalContractNo} gefunden.")
logBuilder.append("Info:\t\tKeine Fristen fuer den Vertrag ${internalContractNo} gefunden." + System.getProperty("line.separator"))
} else {
// Tabellen und Abhaengigkeiten
def termTables = ["terms_idp_ids" : "Term_id",
"terms_term_metadata": "Term_id",
"terms_term_rem_esc" : "term_id",
"terms_term_callback": "term_id",
"terms_term_links" : "Term_id",
"terms_term" : "id",
"terms_interval" : "id"]
termIds."id"?.each { id ->
termTables.each { table, column ->
try {
def deleteQuery = "DELETE FROM ${table} WHERE ${column} = ?"
if (d3.sql.execute(deleteQuery, [id]) == 1) {
d3.log.debug("groovyhook - Eintrag aus Tabelle ${table} mit ID ${id} erfolgreich geloescht.")
logBuilder.append("Info:\t\tEintrag aus Tabelle ${table} mit ID ${id} erfolgreich geloescht." + System.getProperty("line.separator"))
} else {
d3.log.debug("groovyhook - Eintrag aus Tabelle ${table} mit ID ${id} nicht gefunden.")
logBuilder.append("Info:\t\tEintrag aus Tabelle ${table} mit ID ${id} nicht gefunden." + System.getProperty("line.separator"))
}
} catch (D3Exception e) {
error = true
d3.log.error("groovyhook - Fehler beim Loeschen der Eintraege aus Tabelle ${table} mit ID ${id}: ${e}")
logBuilder.append("Error:\t\tFehler beim Loeschen der Eintraege aus Tabelle ${table} mit ID ${id}: ${e}" + System.getProperty("line.separator"))
}
}
}
}
logBuilder.append("\t\t--------------------------------------------------------------------------------" + System.getProperty("line.separator"))
}
// Loeschen von Aufgaben fuer die Dokumenten ID
if (!onlyTerms) {
logBuilder.append("Info\tEs sollen die Aktivitaeten fuer den Vertrag ${internalContractNo} geloescht werden!" + System.getProperty("line.separator"))
def activityIds = d3.sql.executeAndGet("SELECT DISTINCT id FROM terms_activity WHERE context_id = ?", [internalContractNo])
if (!activityIds || activityIds.isEmpty()) {
d3.log.info("groovyhook - Keine Aktivitaeten fuer den Vertrag ${internalContractNo} gefunden.")
logBuilder.append("Info:\t\tKeine Aktivitaeten fuer den Vertrag ${internalContractNo} gefunden." + System.getProperty("line.separator"))
}
def activityTables = ["terms_activity_detail": "activity_id",
"terms_activity_data" : "id",
"terms_activity" : "id"]
activityIds."id"?.each { id ->
activityTables.each { table, column ->
try {
def deleteQuery = "DELETE FROM ${table} WHERE ${column} = ?"
if (d3.sql.execute(deleteQuery, [id]) == 1) {
d3.log.debug("groovyhook - Eintrag aus Tabelle ${table} mit ID ${id} erfolgreich geloescht.")
logBuilder.append("Info:\t\tEintrag aus Tabelle ${table} mit ID ${id} erfolgreich geloescht." + System.getProperty("line.separator"))
} else {
d3.log.debug("groovyhook - Eintrag aus Tabelle ${table} mit ID ${id} nicht gefunden.")
logBuilder.append("Info:\t\tEintrag aus Tabelle ${table} mit ID ${id} nicht gefunden." + System.getProperty("line.separator"))
}
} catch (D3Exception e) {
error = true
d3.log.error("groovyhook - Fehler beim Loeschen der Eintraege aus Tabelle ${table} mit ID ${id}: ${e}")
logBuilder.append("Error:\t\tFehler beim Loeschen der Eintraege aus Tabelle ${table} mit ID ${id}: ${e}" + System.getProperty("line.separator"))
}
}
}
logBuilder.append("\t\t--------------------------------------------------------------------------------" + System.getProperty("line.separator"))
logBuilder.append("Info:\tEs sollen die Aufgaben fuer den Vertrag ${internalContractNo} geloescht werden!" + System.getProperty("line.separator"))
def caseActivityIds = d3.sql.executeAndGet("SELECT DISTINCT act_id FROM dbsCase_activity WHERE internal_contract_number = ?", [internalContractNo])
def caseActivityTables = ["dbsCase_activity_recip": "activity_id",
"dbsCase_activity_cond" : "act_id",
"dbsCase_activity" : "act_id"]
caseActivityIds."act_id"?.each { id ->
caseActivityTables.each { table, column ->
try {
def deleteQuery = "DELETE FROM ${table} WHERE ${column} = ?"
if (d3.sql.execute(deleteQuery, [id]) == 1) {
d3.log.debug("groovyhook - Eintrag aus Tabelle ${table} mit ID ${id} erfolgreich geloescht.")
logBuilder.append("Info:\t\tEintrag aus Tabelle ${table} mit ID ${id} erfolgreich geloescht." + System.getProperty("line.separator"))
} else {
if (table == "dbsCase_activity_cond") {
d3.log.debug("groovyhook - Es gibt keine Bedingungen für die CMC Aufgabe ${id}.")
logBuilder.append("Info:\t\tEs gibt keine Bedingungen für die CMC Aufgabe ${id}." + System.getProperty("line.separator"))
} else {
d3.log.debug("groovyhook - Eintrag aus Tabelle ${table} mit ID ${id} nicht gefunden.")
logBuilder.append("Info:\t\tEintrag aus Tabelle ${table} mit ID ${id} nicht gefunden." + System.getProperty("line.separator"))
}
}
} catch (D3Exception e) {
error = true
d3.log.error("groovyhook - Fehler beim Loeschen der Eintraege aus Tabelle ${table} mit ID ${id}: ${e}")
logBuilder.append("Error:\t\tFehler beim Loeschen der Eintraege aus Tabelle ${table} mit ID ${id}: ${e}" + System.getProperty("line.separator"))
}
}
}
def sessionApiKey = getAuthSession(d3)
//Ermitteln der Task ID
def uriTaskSearch = "${baseUri}/task/api/tasks/search"
CloseableHttpClient client = HttpClientBuilder.create().build()
try {
HttpPost post = new HttpPost(uriTaskSearch)
// JSON Inhalt
def body = """{
"orderBy": "received",
"orderDir": "ASC",
"filter": {
"metadata": {
"key": [
"internalCaseNumber"
],
"values": [
"$internalContractNo"
]
}
}
}"""
StringEntity params = new StringEntity(body, "UTF-8")
post.addHeader("authorization", "Bearer " + sessionApiKey)
post.addHeader("content-type", "application/json")
post.setEntity(params)
CloseableHttpResponse response = client.execute(post)
try {
if (response.getStatusLine().getStatusCode() == 200 || response.getStatusLine().getStatusCode() == 201) {
def js = new JsonSlurper()
def parsedJson = js.parseText(EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8))
def taskIds = parsedJson.tasks?.id?.collect { it.toString() }
def taskSubjects = parsedJson.tasks?.subject?.collect { it.toString() }
if (!taskIds || taskIds.isEmpty()) {
d3.log.info("groovyhook - Es gibt keine Aufgaben zum Vertrag ${internalContractNo}")
logBuilder.append("Info:\t\tEs gibt keine Aufgaben zum Vertrag ${internalContractNo}" + System.getProperty("line.separator"))
} else {
for (def taskId : taskIds) {
for (def taskSubject : taskSubjects) {
d3.log.info("groovyhook - Task ID zum Vertrag ${internalContractNo}: ${taskId}")
logBuilder.append("Info:\t\tTask ID zum Vertrag ${internalContractNo}: ${taskId}" + System.getProperty("line.separator"))
//Loeschen der Aufgabe
def uriTaskDelete = "${baseUri}/task/tasks/${taskId}"
def delete = new HttpDelete(uriTaskDelete)
delete.addHeader("authorization", "Bearer " + sessionApiKey)
response = client.execute(delete)
try {
if (response.getStatusLine().getStatusCode() == 200 || response.getStatusLine().getStatusCode() == 201) {
d3.log.info("groovyhook - Task $taskSubject zum Vertrag ${internalContractNo} wurde erfoglreich geloescht")
logBuilder.append("Info:\t\tTask $taskSubject zum Vertrag ${internalContractNo} wurde erfoglreich geloescht" + System.getProperty("line.separator"))
} else if (!(response.getStatusLine().getStatusCode() == 404)) {
d3.log.error("groovyhook - Task $taskId zum Vertrag ${internalContractNo} mit Betreff $taskSubject konnte nicht geloescht werden: HTTP ${response.getStatusLine().getStatusCode()}")
logBuilder.append("Error:\t\tTask $taskId zum Vertrag ${internalContractNo} mit Betreff $taskSubject konnte nicht geloescht werden: HTTP ${response.getStatusLine().getStatusCode()}" + System.getProperty("line.separator"))
}
} catch (D3Exception e) {
d3.log.error("groovyhook - Fehler beim Ausführen von TaskDelete: ${e}")
logBuilder.append("Error:\t\tFehler beim Ausführen von TaskDelete: ${e}" + System.getProperty("line.separator"))
}
finally {
response.close()
}
}
}
}
} else {
d3.log.error("groovyhook - Task ID zum Vertrag ${internalContractNo} konnte nicht ermittelt werden: HTTP ${response.getStatusLine().getStatusCode()}")
logBuilder.append("Error:\t\tTask ID zum Vertrag ${internalContractNo} konnte nicht ermittelt werden: HTTP ${response.getStatusLine().getStatusCode()}" + System.getProperty("line.separator"))
}
} finally {
response.close()
}
} catch (D3Exception e) {
d3.log.error("groovyhook - Fehler beim Ausführen von TaskSearch: ${e}")
logBuilder.append("Error:\t\tFehler beim Ausführen von TaskSearch: ${e}" + System.getProperty("line.separator"))
}
logBuilder.append("\t\t--------------------------------------------------------------------------------" + System.getProperty("line.separator"))
}
}
offset += batchSize // Offset für den nächsten Batch erhöhen
}
d3.log.info("groovyhook - END Script ${scriptName}")
logBuilder.append("Info:\tEND Script ${scriptName}" + System.getProperty("line.separator"))
logFile.write(logBuilder.toString())
def getAuthSession(D3Interface d3) {
def lAuthSession = null
def lSessionExpire = null
HashMap<String, String> returnMap = doLogin(d3)
if (returnMap != null) {
lAuthSession = returnMap.get("AuthSessionId")
lSessionExpire = returnMap.get("Expire")
}
if (lAuthSession == null || lAuthSession == "") {
d3.log.error("groovyhook - Keine AuthSession erhalten!")
logBuilder.append("Error:\t\tKeine AuthSession erhalten!" + System.getProperty("line.separator"))
}
return lAuthSession
}
def doLogin(D3Interface d3) {
HashMap<String, String> returnMap = null
def loginStatusCode = 0
CloseableHttpClient client = HttpClientBuilder.create().build()
try {
HttpGet loginCall = new HttpGet(baseUri + "/identityprovider/login")
loginCall.addHeader("authorization", "Bearer " + apiKey)
loginCall.addHeader("origin", baseUri)
loginCall.addHeader("accept", "application/json")
loginCall.addHeader("charset", "utf-8")
CloseableHttpResponse loginResponse = client.execute(loginCall)
try {
loginStatusCode = loginResponse.getStatusLine().getStatusCode()
if (loginStatusCode == 200 || loginStatusCode == 201) {
HttpEntity entity = loginResponse.getEntity()
String json = EntityUtils.toString(entity, StandardCharsets.UTF_8)
Gson gson = new Gson()
returnMap = gson.fromJson(json, HashMap.class)
} else {
d3.log.error("Error ${loginStatusCode} waehrend des Logins!")
logBuilder.append("Error:\t\tError ${loginStatusCode} waehrend des Logins!" + System.getProperty("line.separator"))
}
} finally {
loginResponse.close()
}
} catch (Exception e) {
d3.log.error("groovyhook - Fehler waehrend des Logins: ${e}")
logBuilder.append("Error:\t\tFehler waehrend des Logins: ${e}" + System.getProperty("line.separator"))
} finally {
client.close()
}
return returnMap
}