package utils /** * ----------------------------------------------------------------------------- * FieldCopy (Utility) * ----------------------------------------------------------------------------- * * Zweck * ----- * - Extrahiert Feldwerte aus einem Issue-JSON (Map), wie von Jira REST geliefert * - Baut Update-Payloads für PUT /rest/api/3/issue/{key} * - Unterstützt mehrere Felder per Mapping-Liste * * WICHTIG * ------- * - Kein HTTP hier drin (kein get/put/post). Nur pure Logik. * - ADF (Rich Text / Absatz) wird 1:1 als Map übernommen. * * Mapping-Format * -------------- * List von Maps: * [ * [source: "customfield_11501", target: "customfield_11501", allowNull: false], * [source: "customfield_12345", target: "customfield_99999", allowNull: true ] * ] * * allowNull=false: null wird NICHT geschrieben (Zielfeld bleibt unverändert) * allowNull=true : null wird geschrieben (Zielfeld wird geleert) * ----------------------------------------------------------------------------- */ class FieldCopy { /** * Liest den Rohwert eines Feldes aus dem Issue-JSON. */ static Object getFieldValue(Map issueJson, String fieldId) { if (issueJson == null) return null def fields = issueJson.get("fields") if (!(fields instanceof Map)) return null return (fields as Map).get(fieldId) } /** * Baut einen Update-Body für ein einzelnes Feld. * * @return Map im Format: [fields: [(fieldId): value]] */ static Map buildSingleFieldUpdateBody(String fieldId, Object value) { Map fieldsPayload = [:] fieldsPayload.put(fieldId, value) Map body = [:] body.put("fields", fieldsPayload) return body } /** * Baut einen Update-Body für mehrere Felder anhand der Mapping-Liste. * * @return Map {fields:{...}} oder null, wenn nichts geschrieben werden soll */ static Map buildMultiFieldUpdateBody(Map sourceJson, List fieldMappings) { if (sourceJson == null) return null if (fieldMappings == null || fieldMappings.isEmpty()) return null Map fieldsPayload = [:] for (def m : fieldMappings) { if (!(m instanceof Map)) { continue } String sourceField = (m.get("source") ?: "").toString() if (!sourceField) { continue } String targetField = m.containsKey("target") && m.get("target") != null ? m.get("target").toString() : sourceField boolean allowNull = false if (m.containsKey("allowNull") && m.get("allowNull") != null) { allowNull = (m.get("allowNull") as Boolean) } Object value = getFieldValue(sourceJson, sourceField) // null nur setzen, wenn explizit erlaubt if (value == null && !allowNull) { continue } fieldsPayload.put(targetField, value) } if (fieldsPayload.isEmpty()) { return null } Map body = [:] body.put("fields", fieldsPayload) return body } /** * Hilfsfunktion: Liefert die Source-Feldliste (für Jira "fields" QueryString) * als Komma-Sequenz: "customfield_1,customfield_2" */ static String buildSourceFieldQuery(List fieldMappings) { if (fieldMappings == null || fieldMappings.isEmpty()) return "" List result = [] for (def m : fieldMappings) { if (!(m instanceof Map)) continue def s = m.get("source") if (s == null) continue String sourceField = s.toString() if (!sourceField) continue if (!result.contains(sourceField)) { result.add(sourceField) } } return result.join(",") } }