Create Weclapp_auswertung_der_Kunden.sh
This commit is contained in:
Executable
+455
@@ -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: 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"
|
||||||
|
|
||||||
Reference in New Issue
Block a user