From 50bd7c1def1cba954865081eccf09560d45b3aac Mon Sep 17 00:00:00 2001 From: Andreas Vogel Date: Mon, 16 Feb 2026 13:40:49 +0100 Subject: [PATCH] Create Weclapp_auswertung_der_Kunden.sh --- Weclapp_auswertung_der_Kunden.sh | 455 +++++++++++++++++++++++++++++++ 1 file changed, 455 insertions(+) create mode 100755 Weclapp_auswertung_der_Kunden.sh diff --git a/Weclapp_auswertung_der_Kunden.sh b/Weclapp_auswertung_der_Kunden.sh new file mode 100755 index 0000000..800c4e9 --- /dev/null +++ b/Weclapp_auswertung_der_Kunden.sh @@ -0,0 +1,455 @@ +#!/bin/bash + +WECLAPP_API_KEY="3fcf8ca6-bc33-4239-9033-8f8f78a10019" +WECLAPP_ENDPOINT="https://nextenterprise.weclapp.com/webapp/api/v1" + +# jq erforderlich +if ! command -v jq >/dev/null 2>&1; then + echo "FEHLER: 'jq' ist nicht fehlt" >&2 + exit 1 +fi + +if [[ -z "$WECLAPP_API_KEY" ]]; then + echo "FEHLER: WECLAPP_API_KEY nicht gesetzt." >&2 + exit 1 +fi + + + +log_file="$OUTPUT_FOLDER/weclapp_auswertung_$(date '+%d-%m-%Y').txt" + +exec > >(tee -a "$log_file") 2>&1 + +echo "Logfile: $log_file" +echo "--------------------------------------------------------------" + + +# Alle Kunden abrufen und prüfen, ob die Kunden eine Klassifizierung haben. +ENDPOINT="customer" +weclapp_response=$(curl -sS --compressed -X GET \ +-H "AuthenticationToken: ${WECLAPP_API_KEY}" \ +-H "Accept: application/json" \ +"${WECLAPP_ENDPOINT}/${ENDPOINT}?pageSize=1000") + +# Anzahl Kunden ohne Klassifizierung +no_class_count=$(echo "$weclapp_response" | jq ' +[.result[] +| select((.customerRatingName // "") | tostring | length == 0) +] | length +') + +# Anzahl MSP-Kunden (Klasse B) +msp_count=$(echo "$weclapp_response" | jq ' +[.result[] +| select(.customerRatingName == "B") +] | length +') + + +# Kunden ohne Klassifizierung +echo "--------------------------------------------------------------" +echo "--------------Fehlende-Zuordnung------------------------------" +echo "--------------------------------------------------------------" +echo "Für ${no_class_count} Kunden ist keine Klassifizierung vorgenommen:" +echo "$weclapp_response" | jq -r ' +.result[] +| {company, customerNumber, customerRatingName} +| select((.customerRatingName // "") | tostring | length == 0) +| "- \(.company) (Kundennr: \(.customerNumber))" +' + +echo "" +echo "" +echo "--------------------------------------------------------------" +echo "--------------MSP-Kunden--------------------------------------" +echo "--------------------------------------------------------------" +echo "${msp_count} Kunden haben einen MSP-Vertrag:" + +# >>> ERWEITERUNG: MSP-Kunden-Company in Array speichern (ohne declare -A) +declare -a msp_companies=() +msp_map_file="/tmp/msp_customer_map.$$" +: > "$msp_map_file" + +# Liste + Array befüllen +while IFS= read -r line; do +# line kommt als Tab-getrennt: companycustomerNumbercustomerRatingName +company="${line%%$'\t'*}" +rest="${line#*$'\t'}" +customerNumber="${rest%%$'\t'*}" +rating="${rest#*$'\t'}" + +echo "- ${company} (Kundennr: ${customerNumber}, Klasse: ${rating})" + +# nur sinnvolle Company-Namen speichern (nicht leer / nicht "null") +if [[ -n "$company" && "$company" != "null" ]]; then +msp_companies+=("$company") +printf '%s\t%s\n' "$company" "$customerNumber" >> "$msp_map_file" +fi +done < <( +echo "$weclapp_response" | jq -r ' +.result[] +| {company, customerNumber, customerRatingName} +| select(.customerRatingName == "B") +| "\(.company)\t\(.customerNumber)\t\(.customerRatingName)" +' +) + + +echo "" +echo "Zu prüfende Kunden (Array msp_companies) – Anzahl: ${#msp_companies[@]}" +for c in "${msp_companies[@]}"; do +echo "- $c" +done + + +ENDPOINT="contract" +weclapp_response=$(curl -sS --compressed -X GET \ +-H "AuthenticationToken: ${WECLAPP_API_KEY}" \ +-H "Accept: application/json" \ +"${WECLAPP_ENDPOINT}/${ENDPOINT}?pageSize=1000") + +# Ziel-Datei +tmp_contract_file="/tmp/weclapp_contracts.json" + +# Falls Datei existiert, zuerst löschen +if [ -f "$tmp_contract_file" ]; then +rm -f "$tmp_contract_file" +fi + +# JSON unter /tmp speichern +printf '%s\n' "$weclapp_response" > "$tmp_contract_file" + +echo "Contract-JSON wurde gespeichert unter: $tmp_contract_file" + + + + +echo "" +echo "--------------------------------------------------------------" +echo "--------------MSP-Kunden: Vertrag aus Datei-------------------" +echo "--------------------------------------------------------------" + +tmp_contract_file="/tmp/weclapp_contracts.json" + +if [ ! -f "$tmp_contract_file" ]; then +echo "Fehler: $tmp_contract_file existiert nicht." +rm -f "$msp_map_file" +exit 1 +fi + +now_s=$(date +%s) + +normalize_company() { +printf '%s' "$1" \ +| tr '\n' ' ' \ +| sed -E 's/[[:space:]]+/ /g; s/^ //; s/ $//' \ +| tr '[:upper:]' '[:lower:]' +} + +found_count=0 +not_found_count=0 + + +for company in "${msp_companies[@]}"; do +[ -z "$company" ] && continue +[ "$company" = "null" ] && continue + +key="$(normalize_company "$company")" + +# jq wählt den "besten" Vertrag gemäß Regeln: +# 1) gültig (unbefristet oder endDate in Zukunft) +# 2) innerhalb gültig: UNBEFRISTET, sonst größtes endDate, tie-breaker lastModifiedDate +# 3) wenn kein gültiger: größtes endDate (abgelaufen), tie-breaker lastModifiedDate +result=$( +jq -r --arg key "$key" --argjson now "$now_s" ' +def norm: +tostring +| gsub("\\s+"; " ") +| gsub("^\\s+|\\s+$"; "") +| gsub("\\s*&\\s*"; "&") +| ascii_downcase; + +def endMs: +if (.endDate // null) == null or ((.endDate|tostring|length)==0) then null else .endDate end; + +def endStr: +if (.endDate // null) == null or ((.endDate|tostring|length)==0) then +"UNBEFRISTET" +else +((.endDate/1000) | strftime("%d.%m.%Y")) +end; + +def isValid($now): +(endMs == null) or ((endMs/1000) >= $now); + +# alle möglichen Company-Felder als Keys +def companyKeys: +[ +.invoiceAddress.company?, +.deliveryAddress.company?, +.correspondenceAddress.company? +] +| map(select(. != null and (. | tostring | length) > 0)) +| map(norm) +| unique; + +($key | norm) as $custKey + +# Kandidaten für diese Company (Match wenn irgendein Key passt) +| (.result +| map({ +keys: companyKeys, +id: .id, +interval: (.contractItems[0].interval // ""), +lastModifiedDateMs: (.lastModifiedDate // 0), +endDateMs: endMs, +endDateStr: endStr, +valid: (isValid($now)), +contractStatus: (.contractStatus // "") +}) +| map(select(.keys | any(. == $custKey))) +) as $matches + +| if ($matches|length) == 0 then +empty +else +($matches | map(select(.valid))) as $valids +| if ($valids|length) > 0 then +# gültige: UNBEFRISTET bevorzugen, sonst max endDateMs, tie-breaker lastModifiedDateMs +( +($valids | map(select(.endDateMs == null)) | sort_by(.lastModifiedDateMs) | last) +// ($valids +| map(select(.endDateMs != null)) +| sort_by([.endDateMs, .lastModifiedDateMs]) +| last +) +) as $best +| { +id: $best.id, +interval: $best.interval, +end: $best.endDateStr, +status: $best.contractStatus +} +else +# kein gültiger -> letzter abgelaufener (max endDateMs), tie-breaker lastModifiedDateMs +($matches +| map(select(.endDateMs != null)) +| sort_by([.endDateMs, .lastModifiedDateMs]) +| last +) as $best2 +| if $best2 == null then empty +else { +id: $best2.id, +interval: $best2.interval, +end: $best2.endDateStr, +status: $best2.contractStatus +} +end +end +end +' "$tmp_contract_file" +) + +if [ -z "$result" ]; then + echo "Kunde: $company | KEIN_VERTRAG_GEFUNDEN" + not_found_count=$((not_found_count + 1)) +else + cid=$(printf '%s\n' "$result" | jq -r '.id') + interval=$(printf '%s\n' "$result" | jq -r '.interval') + end=$(printf '%s\n' "$result" | jq -r '.end') + status=$(printf '%s\n' "$result" | jq -r '.status') + + cust_nr=$(awk -F'\t' -v c="$company" '$1==c {print $2; exit}' "$msp_map_file") + [ -z "$cust_nr" ] && cust_nr="UNBEKANNT" + + echo "Kunde: $company | Kundennr: $cust_nr | VertragsID: $cid | Interval: $interval | Ende: $end | Status: $status" + found_count=$((found_count + 1)) +fi +done + + +echo "" +echo "--------------------------------------------------------------" +echo "Zusammenfassung:" +echo "Gefundene Verträge: $found_count" +echo "Kein Vertrag gefunden: $not_found_count" +echo "Gesamt MSP-Kunden geprüft: $((found_count + not_found_count))" +echo "--------------------------------------------------------------" + + +echo "" +echo "--------------------------------------------------------------" +echo "--------------MSP-Verträge: Laufzeit endet bald---------------" +echo "--------------------------------------------------------------" + +# Ziel-Datei muss existieren +tmp_contract_file="/tmp/weclapp_contracts.json" +if [ ! -f "$tmp_contract_file" ]; then +echo "Fehler: $tmp_contract_file existiert nicht." +else +# Nächster + übernächster Monat (YYYY-MM) +next_ym=$(date -v+1m "+%Y-%m") +overnext_ym=$(date -v+2m "+%Y-%m") + +# Monatsnamen (z.B. "März 2026") +next_label=$(date -j -f "%Y-%m" "$next_ym" "+%B %Y") +overnext_label=$(date -j -f "%Y-%m" "$overnext_ym" "+%B %Y") + +# Temp-Listen +exp_next_file="/tmp/weclapp_exp_next.$$" +exp_overnext_file="/tmp/weclapp_exp_overnext.$$" +: > "$exp_next_file" +: > "$exp_overnext_file" + +now_s=$(date +%s) + +# Für jeden MSP-Kunden den "besten" Vertrag bestimmen (identische Logik wie zuvor), +# dann prüfen, ob endDate im nächsten/übernächsten Monat liegt +for company in "${msp_companies[@]}"; do +[ -z "$company" ] && continue +[ "$company" = "null" ] && continue + +key="$(normalize_company "$company")" + +result=$( +jq -r --arg key "$key" --argjson now "$now_s" ' +def norm: +tostring +| gsub("\\s+"; " ") +| gsub("^\\s+|\\s+$"; "") +| gsub("\\s*&\\s*"; "&") +| ascii_downcase; + +def endMs: +if (.endDate // null) == null or ((.endDate|tostring|length)==0) then null else .endDate end; + +def endStr: +if (.endDate // null) == null or ((.endDate|tostring|length)==0) then +"UNBEFRISTET" +else +((.endDate/1000) | strftime("%d.%m.%Y")) +end; + +def endYM: +if (endMs == null) then +null +else +((endMs/1000) | strftime("%Y-%m")) +end; + +def isValid($now): +(endMs == null) or ((endMs/1000) >= $now); + +def companyKeys: +[ +.invoiceAddress.company?, +.deliveryAddress.company?, +.correspondenceAddress.company? +] +| map(select(. != null and (. | tostring | length) > 0)) +| map(norm) +| unique; + +($key | norm) as $custKey + +| (.result +| map({ +keys: companyKeys, +id: .id, +interval: (.contractItems[0].interval // ""), +lastModifiedDateMs: (.lastModifiedDate // 0), +endDateMs: endMs, +endDateStr: endStr, +endDateYM: endYM, +valid: (isValid($now)), +contractStatus: (.contractStatus // "") +}) +| map(select(.keys | any(. == $custKey))) +) as $matches + +| if ($matches|length) == 0 then +empty +else +($matches | map(select(.valid))) as $valids +| if ($valids|length) > 0 then +( +($valids | map(select(.endDateMs == null)) | sort_by(.lastModifiedDateMs) | last) +// ($valids + | map(select(.endDateMs != null)) + | sort_by([.endDateMs, .lastModifiedDateMs]) + | last + ) +) as $best +| { + id: $best.id, + interval: $best.interval, + end: $best.endDateStr, + endYM: $best.endDateYM, + status: $best.contractStatus +} +else +($matches +| map(select(.endDateMs != null)) +| sort_by([.endDateMs, .lastModifiedDateMs]) +| last +) as $best2 +| if $best2 == null then empty +else { + id: $best2.id, + interval: $best2.interval, + end: $best2.endDateStr, + endYM: $best2.endDateYM, + status: $best2.contractStatus +} +end +end +end +' "$tmp_contract_file" +) + + # Wenn kein Vertrag gefunden oder UNBEFRISTET -> überspringen + [ -z "$result" ] && continue + + endYM=$(printf '%s\n' "$result" | jq -r '.endYM // empty') + [ -z "$endYM" ] && continue # UNBEFRISTET oder keine endDate + + cid=$(printf '%s\n' "$result" | jq -r '.id') + interval=$(printf '%s\n' "$result" | jq -r '.interval') + end=$(printf '%s\n' "$result" | jq -r '.end') + status=$(printf '%s\n' "$result" | jq -r '.status') + + cust_nr=$(awk -F'\t' -v c="$company" '$1==c {print $2; exit}' "$msp_map_file") + [ -z "$cust_nr" ] && cust_nr="UNBEKANNT" + + line="- $company (Kundennr: $cust_nr | VertragsID: $cid | Interval: $interval | Ende: $end | Status: $status)" + + if [ "$endYM" = "$next_ym" ]; then + printf '%s\n' "$line" >> "$exp_next_file" + elif [ "$endYM" = "$overnext_ym" ]; then + printf '%s\n' "$line" >> "$exp_overnext_file" + fi + done + + echo "" + echo "Die folgenden Verträge laufen im nächsten Monat ($next_label) aus:" + if [ -s "$exp_next_file" ]; then + cat "$exp_next_file" + else + echo "- (keine)" + fi + + echo "" + echo "Die folgenden Verträge laufen im übernächsten Monat ($overnext_label) aus:" + if [ -s "$exp_overnext_file" ]; then + cat "$exp_overnext_file" + else + echo "- (keine)" + fi + + rm -f "$exp_next_file" "$exp_overnext_file" +fi + +# Cleanup +rm -f "$msp_map_file" +rm -f "$tmp_contract_file" + \ No newline at end of file