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