Files
Gitea/Weclapp_auswertung_der_Kunden.sh
2026-02-16 13:40:49 +01:00

455 lines
12 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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: company<TAB>customerNumber<TAB>customerRatingName
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"