From 42b766b31ea6da0d80aa7da49b5863a7e6472e05 Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 6 Jan 2026 19:59:07 +0100 Subject: [PATCH] Add scripts for managing e-conomic customer numbers - Implemented fix_economic_numbers.sh to correct invalid 10-digit economic_customer_number entries in the database. - Created import_economic_csv.py for importing customers from a CSV file into the Hub database, handling updates and new entries. - Developed match_all_customers.sh to match all customers from a CSV file to the Hub database, updating or creating records as necessary. - Added simple_match.sh for a straightforward matching process of customers from a CSV file to the Hub database. --- Kunder-2.xlsx | Bin 0 -> 35667 bytes scripts/fix_economic_numbers.sh | 83 ++++++++++++++++++ scripts/import_economic_csv.py | 85 +++++++++++++++++++ scripts/match_all_customers.sh | 145 ++++++++++++++++++++++++++++++++ scripts/simple_match.sh | 58 +++++++++++++ 5 files changed, 371 insertions(+) create mode 100644 Kunder-2.xlsx create mode 100644 scripts/fix_economic_numbers.sh create mode 100644 scripts/import_economic_csv.py create mode 100644 scripts/match_all_customers.sh create mode 100644 scripts/simple_match.sh diff --git a/Kunder-2.xlsx b/Kunder-2.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..fca5d9383bc53902e6ac876a247874fb5ed40862 GIT binary patch literal 35667 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 BhP(g( literal 0 HcmV?d00001 diff --git a/scripts/fix_economic_numbers.sh b/scripts/fix_economic_numbers.sh new file mode 100644 index 0000000..6ebb4d0 --- /dev/null +++ b/scripts/fix_economic_numbers.sh @@ -0,0 +1,83 @@ +#!/bin/bash + +# Script til at rette forkerte 10-cifrede e-conomic kundenumre +# Baseret på CSV eksport fra e-conomic + +set -e + +CONTAINER_NAME="bmc-hub-postgres-prod" +DB_USER="bmc_hub" +DB_NAME="bmc_hub" + +# Farver til output +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +echo -e "${GREEN}🔍 Finder kunder med forkerte 10-cifrede economic_customer_number...${NC}" + +# Find alle kunder med 10+ cifrede numre (over 999999999) +echo "SELECT id, name, economic_customer_number FROM customers WHERE economic_customer_number > 999999999 ORDER BY economic_customer_number;" | \ +sudo podman exec -i "$CONTAINER_NAME" psql -U "$DB_USER" -d "$DB_NAME" + +echo "" +echo -e "${YELLOW}⚠️ Disse numre er ugyldige i e-conomic (max 9 cifre tilladt)${NC}" +echo "" + +# Ret specifikke kendte cases fra CSV +echo -e "${GREEN}🔧 Retter kendte forkerte numre...${NC}" + +# PFA kunder med forkerte numre - baseret på mønstre i CSV +# 2065328011 skal være 20653280X (find det rigtige i e-conomic) +# 2065328014 skal være 206532814 eller lignende + +# Først: Fjern sidste ciffer hvis det er 1 og nummeret eksisterer i e-conomic +echo -e "${YELLOW}📋 Strategi: Fjerner sidste ciffer fra 10-cifrede numre${NC}" + +# Hent alle 10-cifrede numre +INVALID_NUMBERS=$(sudo podman exec -i "$CONTAINER_NAME" psql -U "$DB_USER" -d "$DB_NAME" -t -c \ +"SELECT id, economic_customer_number FROM customers WHERE economic_customer_number > 999999999;") + +if [ -z "$INVALID_NUMBERS" ]; then + echo -e "${GREEN}✅ Ingen forkerte numre fundet!${NC}" + exit 0 +fi + +# For hver forkert nummer, prøv at rette det +echo "$INVALID_NUMBERS" | while IFS='|' read -r id number; do + id=$(echo "$id" | xargs) + number=$(echo "$number" | xargs) + + if [ -z "$id" ] || [ -z "$number" ]; then + continue + fi + + # Fjern sidste ciffer + corrected=$((number / 10)) + + echo -e "${YELLOW}Kunde ID $id: $number → $corrected${NC}" + + # Opdater i database + sudo podman exec -i "$CONTAINER_NAME" psql -U "$DB_USER" -d "$DB_NAME" -c \ + "UPDATE customers SET economic_customer_number = $corrected WHERE id = $id;" + + echo -e "${GREEN}✅ Opdateret kunde $id${NC}" +done + +echo "" +echo -e "${GREEN}✅ Rettelser komplet!${NC}" +echo "" +echo -e "${YELLOW}📋 Verificer resultatet:${NC}" + +sudo podman exec -i "$CONTAINER_NAME" psql -U "$DB_USER" -d "$DB_NAME" -c \ +"SELECT id, name, economic_customer_number FROM customers WHERE economic_customer_number > 999999999;" + +REMAINING=$(sudo podman exec -i "$CONTAINER_NAME" psql -U "$DB_USER" -d "$DB_NAME" -t -c \ +"SELECT COUNT(*) FROM customers WHERE economic_customer_number > 999999999;") + +if [ "$REMAINING" -eq 0 ]; then + echo -e "${GREEN}✅ Alle kundenumre er nu gyldige!${NC}" +else + echo -e "${RED}⚠️ $REMAINING kunder har stadig ugyldige numre${NC}" +fi diff --git a/scripts/import_economic_csv.py b/scripts/import_economic_csv.py new file mode 100644 index 0000000..3c16a47 --- /dev/null +++ b/scripts/import_economic_csv.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +""" +Import e-conomic customers fra CSV til Hub database +""" +import sys +import csv +import subprocess + +def run_sql(sql): + """Kør SQL kommando via podman""" + cmd = [ + 'sudo', 'podman', 'exec', '-i', 'bmc-hub-postgres-prod', + 'psql', '-U', 'bmc_hub', '-d', 'bmc_hub', '-t', '-c', sql + ] + result = subprocess.run(cmd, capture_output=True, text=True) + return result.stdout.strip() + +def main(): + if len(sys.argv) < 2: + print("Brug: python3 import_economic_csv.py ") + sys.exit(1) + + csv_file = sys.argv[1] + print(f"📂 Læser {csv_file}...") + + updated = 0 + created = 0 + skipped = 0 + + with open(csv_file, 'r', encoding='utf-8-sig') as f: + # Skip første 3 linjer (header osv.) + for _ in range(3): + next(f) + + reader = csv.DictReader(f, delimiter=';') + + for row in reader: + nummer = row.get('Nr.', '').strip() + navn = row.get('Navn', '').strip() + + if not nummer or not navn: + continue + + # Skip non-numeric + if not nummer.isdigit(): + continue + + nummer_int = int(nummer) + + # Skip for store numre + if nummer_int > 999999999: + print(f"⚠️ Springer over {navn} - Nummer for stort: {nummer}") + skipped += 1 + continue + + print(f"[{updated + created + skipped + 1}] {nummer} - {navn}") + + # Escape quotes + navn_esc = navn.replace("'", "''") + + # Find kunde + find_sql = f"SELECT id FROM customers WHERE LOWER(name) = LOWER('{navn_esc}') LIMIT 1;" + kunde_id = run_sql(find_sql).strip() + + if kunde_id and kunde_id.isdigit(): + # Update + update_sql = f"UPDATE customers SET economic_customer_number = {nummer_int} WHERE id = {kunde_id};" + run_sql(update_sql) + print(f" ✅ Opdateret ID {kunde_id}") + updated += 1 + else: + # Create + create_sql = f"INSERT INTO customers (name, economic_customer_number, created_at, updated_at) VALUES ('{navn_esc}', {nummer_int}, NOW(), NOW());" + run_sql(create_sql) + print(f" ➕ Oprettet") + created += 1 + + print(f"\n✅ Færdig!") + print(f" Opdateret: {updated}") + print(f" Oprettet: {created}") + print(f" Sprunget over: {skipped}") + print(f" Total: {updated + created}") + +if __name__ == '__main__': + main() diff --git a/scripts/match_all_customers.sh b/scripts/match_all_customers.sh new file mode 100644 index 0000000..1e9662a --- /dev/null +++ b/scripts/match_all_customers.sh @@ -0,0 +1,145 @@ +#!/bin/bash + +# Script til at matche ALLE kunder fra e-conomic CSV til Hub database +# Opdaterer economic_customer_number baseret på kunde navn match + +# VIGTIGT: Ingen set -e her - vi vil fortsætte ved fejl +set +e + +CONTAINER_NAME="bmc-hub-postgres-prod" +DB_USER="bmc_hub" +DB_NAME="bmc_hub" +CSV_FILE="$1" + +# Farver +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' + +if [ -z "$CSV_FILE" ]; then + echo -e "${RED}❌ Brug: $0 ${NC}" + echo "" + echo "Eksempel: $0 ~/Downloads/Kunder-2.csv" + exit 1 +fi + +if [ ! -f "$CSV_FILE" ]; then + echo -e "${RED}❌ Fil ikke fundet: $CSV_FILE${NC}" + exit 1 +fi + +echo -e "${GREEN}📂 Læser CSV fil: $CSV_FILE${NC}" + +# Vis første 10 linjer for debugging +echo -e "${YELLOW}📋 Første linjer i CSV:${NC}" +head -10 "$CSV_FILE" +echo "" + +# Statistik +TOTAL=0 +MATCHED=0 +UPDATED=0 +SKIPPED=0 +ERRORS=0 + +# Lav temp fil med data +TEMP_FILE=$(mktemp) +tail -n +5 "$CSV_FILE" | grep -v "^$" > "$TEMP_FILE" + +echo -e "${GREEN}🔢 Antal linjer i CSV: $(wc -l < "$TEMP_FILE")${NC}" +echo "" + +# Parse CSV og match kunder +# Format: Nr.;Navn;Gruppe;Attention;Saldo;Forfalden;E-mail +while IFS=';' read -r nummer navn gruppe attention saldo forfalden email rest || [ -n "$nummer" ]; do + # Skip tomme linjer og header + if [ -z "$nummer" ] || [ "$nummer" = "Nr." ]; then + continue + fi + + # Trim whitespace og fjern BOM/special chars + nummer=$(echo "$nummer" | xargs | tr -cd '0-9') + navn=$(echo "$navn" | xargs) + + if [ -z "$navn" ] || [ -z "$nummer" ]; then + echo -e "${RED}DEBUG: Skipping empty - nummer='$nummer', navn='$navn'${NC}" + continue + fi + + TOTAL=$((TOTAL + 1)) + + # Debug ALLE linjer + echo -e "${YELLOW}[$TOTAL] Processing: $nummer - $navn${NC}" + + # Escape single quotes i navn + navn_escaped=$(echo "$navn" | sed "s/'/''/g") + + # Tjek om nummer er gyldigt (max 9 cifre) + if [ "$nummer" -gt 999999999 ] 2>/dev/null; then + echo -e "${YELLOW}⚠️ Springer over $navn - Nummer for stort: $nummer${NC}" + SKIPPED=$((SKIPPED + 1)) + continue + fi + + # Find matchende kunde i Hub + MATCH=$(sudo podman exec -i "$CONTAINER_NAME" psql -U "$DB_USER" -d "$DB_NAME" -t -c \ + "SELECT id FROM customers WHERE LOWER(TRIM(name)) = LOWER(TRIM('$navn_escaped')) LIMIT 1;") + + MATCH=$(echo "$MATCH" | xargs) + + if [ -n "$MATCH" ]; then + MATCHED=$((MATCHED + 1)) + + # Opdater economic_customer_number (altid - tvungen opdatering) + UPDATE_RESULT=$(sudo podman exec -i "$CONTAINER_NAME" psql -U "$DB_USER" -d "$DB_NAME" -t -c \ + "UPDATE customers SET economic_customer_number = $nummer, last_synced_at = NOW() + WHERE id = $MATCH + RETURNING id;" 2>&1) + + if echo "$UPDATE_RESULT" | grep -q "^[0-9]"; then + echo -e "${GREEN}✅ $navn → e-conomic #$nummer (opdateret)${NC}" + UPDATED=$((UPDATED + 1)) + else + echo -e "${YELLOW}⏭️ $navn - Ingen ændring nødvendig${NC}" + fi + else + # Kunde findes ikke i Hub - opret den + CREATE_RESULT=$(sudo podman exec -i "$CONTAINER_NAME" psql -U "$DB_USER" -d "$DB_NAME" -t -c \ + "INSERT INTO customers (name, economic_customer_number, created_at, updated_at) + VALUES ('$navn_escaped', $nummer, NOW(), NOW()) + ON CONFLICT DO NOTHING + RETURNING id;" 2>&1) + + if echo "$CREATE_RESULT" | grep -q "^[0-9]"; then + echo -e "${GREEN}➕ OPRETTET: $navn → e-conomic #$nummer${NC}" + UPDATED=$((UPDATED + 1)) + else + echo -e "${YELLOW}⚠️ Kunne ikke oprette: $navn (e-conomic #$nummer)${NC}" + SKIPPED=$((SKIPPED + 1)) + fi + fi + + # Progress hver 50. kunde + if [ $((TOTAL % 50)) -eq 0 ] && [ $TOTAL -gt 0 ]; then + echo -e "${YELLOW}📊 Progress: $TOTAL behandlet, $MATCHED matched, $UPDATED opdateret${NC}" + fi +done < "$TEMP_FILE" + +# Cleanup +rm -f "$TEMP_FILE" + +echo "" +echo -e "${GREEN}✅ Matching komplet!${NC}" +echo -e "${GREEN}📊 Statistik:${NC}" +echo -e " Total behandlet: $TOTAL" +echo -e " Matched i Hub: $MATCHED" +echo -e " Opdateret: $UPDATED" +echo -e " Sprunget over: $SKIPPED" +echo "" + +# Vis kunder der mangler economic_customer_number +MISSING=$(sudo podman exec -i "$CONTAINER_NAME" psql -U "$DB_USER" -d "$DB_NAME" -t -c \ +"SELECT COUNT(*) FROM customers WHERE economic_customer_number IS NULL;") + +echo -e "${YELLOW}⚠️ $MISSING kunder mangler stadig economic_customer_number${NC}" diff --git a/scripts/simple_match.sh b/scripts/simple_match.sh new file mode 100644 index 0000000..22ebf61 --- /dev/null +++ b/scripts/simple_match.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# Simpel version - ingen fancy features +CSV_FILE="$1" +CONTAINER="bmc-hub-postgres-prod" + +if [ -z "$CSV_FILE" ]; then + echo "Brug: $0 " + exit 1 +fi + +echo "Reading $CSV_FILE..." +LINE_NO=0 +UPDATED=0 + +while IFS=';' read -r nummer navn rest; do + LINE_NO=$((LINE_NO + 1)) + + # Skip første 4 linjer + if [ $LINE_NO -le 4 ]; then + continue + fi + + # Clean nummer og navn + nummer=$(echo "$nummer" | tr -cd '0-9') + navn=$(echo "$navn" | xargs) + + # Skip hvis tomt + if [ -z "$nummer" ] || [ -z "$navn" ]; then + continue + fi + + echo "[$LINE_NO] $nummer - $navn" + + # Escape quotes + navn_esc=$(echo "$navn" | sed "s/'/''/g") + + # Find kunde + ID=$(sudo podman exec -i "$CONTAINER" psql -U bmc_hub -d bmc_hub -t -c \ + "SELECT id FROM customers WHERE LOWER(name) = LOWER('$navn_esc') LIMIT 1;" | xargs) + + if [ -n "$ID" ]; then + # Update + sudo podman exec -i "$CONTAINER" psql -U bmc_hub -d bmc_hub -c \ + "UPDATE customers SET economic_customer_number = $nummer WHERE id = $ID;" > /dev/null + echo " ✅ Updated ID $ID" + UPDATED=$((UPDATED + 1)) + else + # Create + sudo podman exec -i "$CONTAINER" psql -U bmc_hub -d bmc_hub -c \ + "INSERT INTO customers (name, economic_customer_number, created_at, updated_at) VALUES ('$navn_esc', $nummer, NOW(), NOW());" > /dev/null + echo " ➕ Created" + UPDATED=$((UPDATED + 1)) + fi +done < "$CSV_FILE" + +echo "" +echo "Done! Updated: $UPDATED customers"