648 lines
21 KiB
Markdown
648 lines
21 KiB
Markdown
# Changelog - BizMatch Project
|
|
|
|
Dokumentation aller wichtigen Änderungen am BizMatch-Projekt. Diese Datei listet Feature-Implementierungen, Bugfixes, Datenbank-Migrationen und architektonische Verbesserungen auf.
|
|
|
|
---
|
|
|
|
## Inhaltsverzeichnis
|
|
|
|
1. [Datenbank-Änderungen](#1-datenbank-änderungen)
|
|
2. [Backend-Änderungen](#2-backend-änderungen)
|
|
3. [Frontend-Änderungen](#3-frontend-änderungen)
|
|
4. [SEO-Verbesserungen](#4-seo-verbesserungen)
|
|
5. [Code-Cleanup & Wartung](#5-code-cleanup--wartung)
|
|
6. [Bekannte Issues & Workarounds](#6-bekannte-issues--workarounds)
|
|
|
|
---
|
|
|
|
## 1) Datenbank-Änderungen
|
|
|
|
### 1.1 Schema-Migration: JSON-basierte Speicherung
|
|
|
|
**Datum:** November 2025
|
|
**Status:** ✅ Abgeschlossen
|
|
|
|
#### Zusammenfassung der Änderungen
|
|
|
|
Die Datenbank wurde von einem **relationalen Schema** zu einem **JSON-basierten Schema** migriert. Dies bedeutet:
|
|
|
|
- ✅ **Neue Tabellen wurden erstellt** (`users_json`, `businesses_json`, `commercials_json`)
|
|
- ❌ **Alte Tabellen wurden NICHT gelöscht** (`users`, `businesses`, `commercials` existieren noch)
|
|
- ✅ **Alle Daten wurden migriert** (kopiert von alten zu neuen Tabellen)
|
|
- ✅ **Anwendung nutzt ausschließlich neue Tabellen** (alte Tabellen dienen nur als Backup)
|
|
|
|
#### Detaillierte Tabellenstruktur
|
|
|
|
**ALTE Tabellen (nicht mehr in Verwendung, aber noch vorhanden):**
|
|
|
|
```sql
|
|
-- users (relational)
|
|
CREATE TABLE users (
|
|
id UUID PRIMARY KEY,
|
|
email VARCHAR(255),
|
|
firstname VARCHAR(100),
|
|
lastname VARCHAR(100),
|
|
phone VARCHAR(50),
|
|
location_name VARCHAR(255),
|
|
location_state VARCHAR(2),
|
|
location_latitude FLOAT,
|
|
location_longitude FLOAT,
|
|
customer_type VARCHAR(50),
|
|
customer_sub_type VARCHAR(50),
|
|
show_in_directory BOOLEAN,
|
|
created TIMESTAMP,
|
|
updated TIMESTAMP,
|
|
-- ... weitere 20+ Spalten
|
|
);
|
|
|
|
-- businesses (relational)
|
|
CREATE TABLE businesses (
|
|
id UUID PRIMARY KEY,
|
|
email VARCHAR(255),
|
|
title VARCHAR(500),
|
|
asking_price DECIMAL,
|
|
established INTEGER,
|
|
revenue DECIMAL,
|
|
cash_flow DECIMAL,
|
|
-- ... weitere 30+ Spalten für alle Business-Eigenschaften
|
|
);
|
|
|
|
-- commercials (relational)
|
|
CREATE TABLE commercials (
|
|
id UUID PRIMARY KEY,
|
|
email VARCHAR(255),
|
|
title VARCHAR(500),
|
|
asking_price DECIMAL,
|
|
property_type VARCHAR(100),
|
|
-- ... weitere 25+ Spalten für alle Property-Eigenschaften
|
|
);
|
|
```
|
|
|
|
**NEUE Tabellen (aktuell in Verwendung):**
|
|
|
|
```sql
|
|
-- users_json (JSON-basiert)
|
|
CREATE TABLE users_json (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
email VARCHAR(255) UNIQUE NOT NULL,
|
|
data JSONB NOT NULL
|
|
);
|
|
|
|
-- businesses_json (JSON-basiert)
|
|
CREATE TABLE businesses_json (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
email VARCHAR(255) NOT NULL,
|
|
data JSONB NOT NULL
|
|
);
|
|
|
|
-- commercials_json (JSON-basiert)
|
|
CREATE TABLE commercials_json (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
email VARCHAR(255) NOT NULL,
|
|
data JSONB NOT NULL
|
|
);
|
|
```
|
|
|
|
#### Was wurde NICHT geändert
|
|
|
|
**❌ Folgende Dinge wurden NICHT geändert:**
|
|
|
|
1. **Alte Tabellen existieren weiterhin** - Sie wurden nicht gelöscht, um als Backup zu dienen
|
|
2. **Datenbank-Name** - Weiterhin `bizmatch` (keine Änderung)
|
|
3. **Datenbank-User** - Weiterhin `bizmatch` (keine Änderung)
|
|
4. **Datenbank-Passwort** - Keine Änderung
|
|
5. **Datenbank-Port** - Weiterhin `5432` (keine Änderung)
|
|
6. **Docker-Container-Name** - Weiterhin `bizmatchdb` (keine Änderung)
|
|
7. **Indices** - PostgreSQL JSONB-Indices wurden automatisch erstellt
|
|
|
|
#### Was wurde geändert
|
|
|
|
**✅ Folgende Dinge wurden geändert:**
|
|
|
|
1. **Anwendungs-Code verwendet nur noch neue Tabellen:**
|
|
- Backend liest/schreibt nur noch in `users_json`, `businesses_json`, `commercials_json`
|
|
- Drizzle ORM Schema wurde aktualisiert (`bizmatch-server/src/drizzle/schema.ts`)
|
|
- Alle Services wurden angepasst (user.service.ts, business-listing.service.ts, etc.)
|
|
|
|
2. **Datenstruktur in JSONB-Spalten:**
|
|
- Alle Felder, die vorher einzelne Spalten waren, sind jetzt in der `data`-Spalte als JSON
|
|
- Nested Objects möglich (z.B. `location` mit `name`, `state`, `latitude`, `longitude`)
|
|
- Arrays direkt im JSON speicherbar (z.B. `imageOrder`, `areasServed`)
|
|
|
|
3. **Query-Syntax:**
|
|
- Statt `WHERE firstname = 'John'` → `WHERE (data->>'firstname') = 'John'`
|
|
- Statt `WHERE location_state = 'TX'` → `WHERE (data->'location'->>'state') = 'TX'`
|
|
- Haversine-Formel für Radius-Suche nutzt jetzt JSON-Pfade
|
|
|
|
#### Beispiel: User-Datensatz Vorher/Nachher
|
|
|
|
**VORHER (relationale Tabelle `users`):**
|
|
|
|
| id | email | firstname | lastname | phone | location_name | location_state | location_latitude | location_longitude | customer_type | customer_sub_type | show_in_directory | created | updated |
|
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
| abc-123 | john@example.com | John | Doe | +1-555-0123 | Austin | TX | 30.2672 | -97.7431 | professional | broker | true | 2025-11-01 | 2025-11-25 |
|
|
|
|
**NACHHER (JSON-Tabelle `users_json`):**
|
|
|
|
| id | email | data (JSONB) |
|
|
|---|---|---|
|
|
| abc-123 | john@example.com | `{"firstname": "John", "lastname": "Doe", "phone": "+1-555-0123", "location": {"name": "Austin", "state": "TX", "latitude": 30.2672, "longitude": -97.7431}, "customerType": "professional", "customerSubType": "broker", "showInDirectory": true, "created": "2025-11-01T10:00:00Z", "updated": "2025-11-25T15:30:00Z"}` |
|
|
|
|
#### Vorteile der neuen Struktur
|
|
|
|
- ✅ **Keine Schema-Migrationen mehr nötig** - Neue Felder einfach im JSON hinzufügen
|
|
- ✅ **Flexiblere Datenstrukturen** - Nested Objects und Arrays direkt speicherbar
|
|
- ✅ **Einfacheres ORM-Mapping** - TypeScript-Interfaces direkt zu JSON serialisierbar
|
|
- ✅ **Bessere Performance** - PostgreSQL JSONB ist indexierbar und schnell durchsuchbar
|
|
- ✅ **Reduzierte Code-Komplexität** - Weniger Join-Operationen, weniger Spalten-Mapping
|
|
|
|
#### Migration durchführen (Referenz)
|
|
|
|
Die Migration wurde bereits durchgeführt. Falls nötig, Backup-Prozess:
|
|
|
|
```bash
|
|
# 1. Backup der alten relationalen Tabellen
|
|
docker exec -it bizmatchdb \
|
|
pg_dump -U bizmatch -d bizmatch -t users -t businesses -t commercials \
|
|
-F c -Z 9 -f /tmp/backup_relational_tables.dump
|
|
|
|
# 2. Neue Tabellen sind bereits vorhanden und in Verwendung
|
|
# 3. Alte Tabellen können bei Bedarf gelöscht werden (NICHT empfohlen vor finalem Produktions-Test)
|
|
```
|
|
|
|
### 1.2 Location-Datenstruktur bei Professionals
|
|
|
|
**Datum:** November 2025
|
|
**Status:** ✅ Abgeschlossen
|
|
|
|
#### Problem
|
|
Professionals-Suche funktionierte nicht, da die Datenstruktur für `location` falsch angenommen wurde.
|
|
|
|
#### Lösung
|
|
- Professionals verwenden `location`-Objekt (nicht `areasServed`-Array)
|
|
- Struktur: `{ name: 'Austin', state: 'TX', latitude: 30.2672, longitude: -97.7431 }`
|
|
|
|
#### Betroffene Queries
|
|
- Exact City Search: `location.name` ILIKE-Vergleich
|
|
- Radius Search: Haversine-Formel mit `location.latitude` und `location.longitude`
|
|
|
|
---
|
|
|
|
## 2) Backend-Änderungen
|
|
|
|
### 2.1 Professionals Search Fix
|
|
|
|
**Datei:** `bizmatch-server/src/user/user.service.ts`
|
|
**Status:** ✅ Abgeschlossen
|
|
|
|
#### Änderungen
|
|
|
|
**Exact City Search (Zeile 28-30):**
|
|
```typescript
|
|
if (criteria.city && criteria.searchType === 'exact') {
|
|
whereConditions.push(sql`(${schema.users_json.data}->'location'->>'name') ILIKE ${criteria.city.name}`);
|
|
}
|
|
```
|
|
|
|
**Radius Search (Zeile 32-36):**
|
|
```typescript
|
|
if (criteria.city && criteria.radius && criteria.searchType === 'radius' && criteria.radius) {
|
|
const cityGeo = this.geoService.getCityWithCoords(criteria.state, criteria.city.name);
|
|
const distanceQuery = getDistanceQuery(schema.users_json, cityGeo.latitude, cityGeo.longitude);
|
|
whereConditions.push(sql`${distanceQuery} <= ${criteria.radius}`);
|
|
}
|
|
```
|
|
|
|
**State Filter (Zeile 55-57):**
|
|
```typescript
|
|
if (criteria.state) {
|
|
whereConditions.push(sql`(${schema.users_json.data}->'location'->>'state') = ${criteria.state}`);
|
|
}
|
|
```
|
|
|
|
**County Filter (Zeile 51-53):**
|
|
```typescript
|
|
if (criteria.counties && criteria.counties.length > 0) {
|
|
whereConditions.push(or(...criteria.counties.map(county =>
|
|
sql`(${schema.users_json.data}->'location'->>'county') ILIKE ${`%${county}%`}`
|
|
)));
|
|
}
|
|
```
|
|
|
|
### 2.2 TypeScript-Fehler behoben
|
|
|
|
**Problem:**
|
|
Kompilierungsfehler wegen falscher Parameter-Übergabe an `getDistanceQuery()`
|
|
|
|
**Lösung:**
|
|
- ❌ Alt: `getDistanceQuery(schema.users_json.data, 'location', lat, lon)`
|
|
- ✅ Neu: `getDistanceQuery(schema.users_json, lat, lon)`
|
|
|
|
### 2.3 Slug-Unterstützung für SEO-freundliche URLs
|
|
|
|
**Status:** ✅ Implementiert
|
|
|
|
Business- und Commercial-Property-Listings können nun über SEO-freundliche Slugs aufgerufen werden:
|
|
|
|
- `/business/austin-coffee-shop-for-sale` statt `/business/uuid-123-456`
|
|
- `/commercial-property/downtown-retail-space-dallas` statt `/commercial-property/uuid-789`
|
|
|
|
**Implementierung:**
|
|
- Automatische Slug-Generierung aus Listing-Titeln
|
|
- Slug-basierte Routen in allen Controllern
|
|
- Fallback auf ID, falls kein Slug vorhanden
|
|
|
|
---
|
|
|
|
## 3) Frontend-Änderungen
|
|
|
|
### 3.1 Breadcrumbs-Navigation
|
|
|
|
**Datum:** November 2025
|
|
**Status:** ✅ Abgeschlossen
|
|
|
|
#### Implementierte Komponenten
|
|
|
|
**Betroffene Seiten:**
|
|
- ✅ Business Detail Pages (`details-business-listing.component.ts`)
|
|
- ✅ Commercial Property Detail Pages (`details-commercial-property-listing.component.ts`)
|
|
- ✅ User Detail Pages (`details-user.component.ts`)
|
|
- ✅ 404 Not Found Page (`not-found.component.ts`)
|
|
- ✅ Business Listings Overview (`business-listings.component.ts`)
|
|
- ✅ Commercial Property Listings Overview (`commercial-property-listings.component.ts`)
|
|
|
|
**Beispiel-Struktur:**
|
|
```
|
|
Home > Commercial Properties > Austin Office Space for Sale
|
|
Home > Business Listings > Restaurant for Sale in Dallas
|
|
Home > 404 - Page Not Found
|
|
```
|
|
|
|
**Komponente:** `bizmatch/src/app/components/breadcrumbs/breadcrumbs.component.ts`
|
|
|
|
### 3.2 Automatische 50-Meilen-Radius-Auswahl
|
|
|
|
**Datum:** November 2025
|
|
**Status:** ✅ Abgeschlossen
|
|
|
|
#### Änderungen
|
|
|
|
Bei Auswahl einer Stadt in den Suchfiltern wird automatisch:
|
|
- **Search Type** auf `"radius"` gesetzt
|
|
- **Radius** auf `50` Meilen gesetzt
|
|
- Filter-UI aktualisiert (Radius-Feld aktiv und ausgefüllt)
|
|
|
|
**Betroffene Dateien:**
|
|
- `bizmatch/src/app/components/search-modal/search-modal.component.ts` (Business)
|
|
- `bizmatch/src/app/components/search-modal/search-modal-commercial.component.ts` (Properties)
|
|
- `bizmatch/src/app/components/search-modal/search-modal-broker.component.ts` (Professionals)
|
|
|
|
**Implementierung (Zeilen 255-269 in search-modal.component.ts):**
|
|
```typescript
|
|
setCity(city: any): void {
|
|
const updates: any = {};
|
|
if (city) {
|
|
updates.city = city;
|
|
updates.state = city.state;
|
|
// Automatically set radius to 50 miles and enable radius search
|
|
updates.searchType = 'radius';
|
|
updates.radius = 50;
|
|
} else {
|
|
updates.city = null;
|
|
updates.radius = null;
|
|
updates.searchType = 'exact';
|
|
}
|
|
this.updateCriteria(updates);
|
|
}
|
|
```
|
|
|
|
### 3.3 Error Handling Verbesserungen
|
|
|
|
**Betroffene Komponenten:**
|
|
- `details-business-listing.component.ts`
|
|
- `details-commercial-property-listing.component.ts`
|
|
|
|
**Änderungen:**
|
|
- ✅ Safe Navigation für `listing.imageOrder` (Null-Check vor forEach)
|
|
- ✅ Verbesserte Error-Message-Extraktion mit Optional Chaining
|
|
- ✅ Default-Breadcrumbs auch bei Fehlerfall
|
|
- ✅ Korrekte Navigation zu 404-Seite bei fehlenden Listings
|
|
|
|
**Beispiel (Zeile 139 in details-commercial-property-listing.component.ts):**
|
|
```typescript
|
|
if (this.listing.imageOrder && Array.isArray(this.listing.imageOrder)) {
|
|
this.listing.imageOrder.forEach(image => {
|
|
const imageURL = `${this.env.imageBaseUrl}/pictures/property/${this.listing.imagePath}/${this.listing.serialId}/${image}`;
|
|
this.images.push(new ImageItem({ src: imageURL, thumb: imageURL }));
|
|
});
|
|
}
|
|
```
|
|
|
|
### 3.4 Business Location Privacy - Stadt-Grenze statt exakter Adresse
|
|
|
|
**Datum:** November 2025
|
|
**Status:** ✅ Abgeschlossen
|
|
|
|
#### Problem & Motivation
|
|
|
|
Bei Business-Listings für verkaufende Unternehmen sollte die **exakte Adresse nicht öffentlich angezeigt** werden, um:
|
|
- ✅ Konkurrierende Unternehmen nicht zu informieren
|
|
- ✅ Kunden nicht zu verunsichern
|
|
- ✅ Mitarbeiter vor Verunsicherung zu schützen
|
|
|
|
Nur die **ungefähre Stadt-Region** soll angezeigt werden. Die genaue Adresse wird erst nach Kontaktaufnahme mitgeteilt.
|
|
|
|
#### Implementierung
|
|
|
|
**Betroffene Dateien:**
|
|
- `bizmatch/src/app/services/geo.service.ts` - Neue Methode `getCityBoundary()`
|
|
- `bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.ts` - Override von Map-Methoden
|
|
|
|
**Unterschied: Business vs. Commercial Property**
|
|
|
|
| Listing-Typ | Map-Anzeige | Adresse-Anzeige | Begründung |
|
|
|---|---|---|---|
|
|
| **Business Listings** | Stadt-Grenze (rotes Polygon) | Nur Stadt, County, State | Privacy: Verkäufer-Schutz |
|
|
| **Commercial Properties** | Exakter Pin-Marker | Vollständige Straßenadresse | Immobilie muss sichtbar sein |
|
|
|
|
**Technische Umsetzung:**
|
|
|
|
1. **Nominatim API Integration** ([geo.service.ts:33-37](bizmatch/src/app/services/geo.service.ts#L33-L37)):
|
|
```typescript
|
|
getCityBoundary(cityName: string, state: string): Observable<any> {
|
|
const query = `${cityName}, ${state}, USA`;
|
|
let headers = new HttpHeaders().set('X-Hide-Loading', 'true').set('Accept-Language', 'en-US');
|
|
return this.http.get(`${this.baseUrl}?q=${encodeURIComponent(query)}&format=json&polygon_geojson=1&limit=1`, { headers });
|
|
}
|
|
```
|
|
|
|
2. **City Boundary Polygon** ([details-business-listing.component.ts:322-430](bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.ts#L322-L430)):
|
|
- Lädt Stadt-Grenz-Polygon von OpenStreetMap Nominatim API
|
|
- Zeigt rote Umrandung der Stadt (wie Google Maps)
|
|
- Unterstützt `Polygon` und `MultiPolygon` Geometrien
|
|
- **Fallback:** 8km-Radius-Kreis bei API-Fehler oder fehlenden Daten
|
|
|
|
3. **Karten-Konfiguration:**
|
|
```typescript
|
|
// Rotes Polygon (wie Google Maps)
|
|
const cityPolygon = polygon(latlngs, {
|
|
color: '#ef4444', // Rot
|
|
fillColor: '#ef4444', // Rot
|
|
fillOpacity: 0.1, // Sehr transparent (90% durchsichtig)
|
|
weight: 2 // Linienstärke
|
|
});
|
|
|
|
// Popup zeigt nur allgemeine Information
|
|
cityPolygon.bindPopup(`
|
|
<div style="padding: 8px;">
|
|
<strong>General Area:</strong><br/>
|
|
${cityName}, ${county ? county + ', ' : ''}${state}<br/>
|
|
<small style="color: #666;">City boundary shown for privacy.<br/>Exact location provided after contact.</small>
|
|
</div>
|
|
`);
|
|
```
|
|
|
|
4. **Address Control Override:**
|
|
- Zeigt nur: "Austin, Travis County, TX"
|
|
- **NICHT** angezeigt: Straßenname, Hausnummer, PLZ
|
|
|
|
5. **OpenStreetMap Link Override:**
|
|
- Zoom-Level 11 (Stadt-Ansicht) statt Zoom-Level 15 (Straßen-Ansicht)
|
|
- Keine Marker auf exakter Position
|
|
|
|
**Entwicklungs-Verlauf (Entscheidungen):**
|
|
|
|
| Ansatz | Grund für Ablehnung | Status |
|
|
|---|---|---|
|
|
| 2km Fuzzy-Radius | Zu klein - bei wenigen Businesses in Stadt identifizierbar | ❌ Abgelehnt |
|
|
| County-Level | Zu groß - schlechte UX, schlechtes SEO | ❌ Abgelehnt |
|
|
| Stadt-Center + 8km-Kreis | Funktioniert, aber nicht professionell aussehend | ⚠️ Fallback |
|
|
| **Stadt-Grenz-Polygon (wie Google Maps)** | Professionell, präzise, gute Privacy | ✅ **Implementiert** |
|
|
|
|
**Vorteile der Lösung:**
|
|
|
|
- ✅ **Privacy by Design** - Exakte Location nicht sichtbar
|
|
- ✅ **Professionelles Erscheinungsbild** - Wie Google Maps Stadt-Grenzen
|
|
- ✅ **Genaue Stadt-Darstellung** - Nutzt offizielle OSM-Daten
|
|
- ✅ **Robust** - Fallback auf Kreis bei API-Problemen
|
|
- ✅ **SEO-freundlich** - Stadt-Namen bleiben in Metadaten erhalten
|
|
- ✅ **Multi-Polygon Support** - Städte mit mehreren Bereichen (Inseln, etc.)
|
|
|
|
**Was NICHT geändert wurde:**
|
|
|
|
- ❌ **Commercial Property Listings** zeigen weiterhin exakte Adressen
|
|
- ❌ **User/Professional Locations** zeigen weiterhin Stadt-Pins
|
|
- ❌ **Datenbank** - Location-Daten bleiben unverändert gespeichert
|
|
- ❌ **Backend** - Keine API-Änderungen nötig
|
|
|
|
---
|
|
|
|
## 4) SEO-Verbesserungen
|
|
|
|
### 4.1 Meta-Tags & Structured Data
|
|
|
|
**Status:** ✅ Implementiert
|
|
|
|
**Neue SEO-Features:**
|
|
- ✅ Dynamische Title & Description für alle Listing-Seiten
|
|
- ✅ Open Graph Tags für Social Media Sharing
|
|
- ✅ JSON-LD Structured Data (Schema.org)
|
|
- ✅ Canonical URLs
|
|
- ✅ Noindex für 404-Seiten
|
|
|
|
**Implementierung:**
|
|
- `bizmatch/src/app/services/seo.service.ts`
|
|
- Automatische Meta-Tag-Generierung basierend auf Listing-Daten
|
|
|
|
### 4.2 Sitemap-Generierung
|
|
|
|
**Status:** ✅ Implementiert
|
|
|
|
**Endpunkte:**
|
|
- `/bizmatch/sitemap.xml` - Haupt-Sitemap (Index)
|
|
- `/bizmatch/sitemap/static.xml` - Statische Seiten
|
|
- `/bizmatch/sitemap/business-1.xml` - Business-Listings (paginiert)
|
|
- `/bizmatch/sitemap/commercial-1.xml` - Commercial-Properties (paginiert)
|
|
|
|
**Controller:** `bizmatch-server/src/sitemap/sitemap.controller.ts`
|
|
|
|
### 4.3 SEO-freundliche 404-Seite
|
|
|
|
**Datei:** `bizmatch/src/app/components/not-found/not-found.component.ts`
|
|
|
|
**Features:**
|
|
- ✅ Breadcrumbs für bessere Navigation
|
|
- ✅ `noindex` Meta-Tag (verhindert Indexierung)
|
|
- ✅ Aussagekräftige Title & Description
|
|
- ✅ Link zurück zur Homepage
|
|
|
|
---
|
|
|
|
## 5) Code-Cleanup & Wartung
|
|
|
|
### 5.1 Gelöschte temporäre Dateien
|
|
|
|
**Datum:** November 2025
|
|
**Status:** ✅ Abgeschlossen
|
|
|
|
**Markdown-Dokumentation (7 Dateien):**
|
|
- ❌ `DATABASE-FIX-INSTRUCTIONS.md`
|
|
- ❌ `DEPLOYMENT-GUIDE.md`
|
|
- ❌ `PROFESSIONALS-TAB-IMPLEMENTATION.md`
|
|
- ❌ `RESTART-BACKEND.md`
|
|
- ❌ `SEO-IMPROVEMENTS-SUMMARY.md`
|
|
- ❌ `bizmatch-server/SEO-DEPLOYMENT-SUCCESS.md`
|
|
- ❌ `bizmatch-server/TYPESCRIPT-FIX-SUMMARY.md`
|
|
|
|
**Shell-Scripts (33 Dateien):**
|
|
- ❌ Alle `.sh`-Dateien in `bizmatch-server/` (check-*, fix-*, test-*, run-*, setup-*, etc.)
|
|
|
|
**SQL-Test-Dateien (5 Dateien):**
|
|
- ❌ `create-schema.sql`
|
|
- ❌ `insert-professionals-json.sql`
|
|
- ❌ `insert-professionals-simple.sql`
|
|
- ❌ `insert-test-professionals.sql`
|
|
- ❌ `insert-test-professionals-fixed.sql`
|
|
|
|
**Debug-JavaScript (2 Dateien):**
|
|
- ❌ `check-db.js`
|
|
- ❌ `verify.js`
|
|
|
|
**Komplette Verzeichnisse:**
|
|
- ❌ `bizmatch-server/scripts/` (~13 Dateien)
|
|
- ❌ `bizmatch-server/src/scripts/` (~13 Dateien)
|
|
- ❌ `.claude/` (Verzeichnis)
|
|
|
|
**Gesamt:** ~75 temporäre Dateien und 3 Verzeichnisse entfernt
|
|
|
|
### 5.2 Beibehaltene Konfigurationsdateien
|
|
|
|
**✅ Wichtige Dateien (nicht gelöscht):**
|
|
- `README.md` (Projekt-Dokumentation)
|
|
- `bizmatch-server/README.md` (Server-Dokumentation)
|
|
- `.eslintrc.js` (Code-Style-Konfiguration)
|
|
- `docker-compose.yml` (Container-Konfiguration)
|
|
- `.gitignore` (Git-Konfiguration)
|
|
|
|
---
|
|
|
|
## 6) Bekannte Issues & Workarounds
|
|
|
|
### 6.1 Docker-Container-Neustart nach Code-Änderungen
|
|
|
|
**Problem:**
|
|
TypeScript-Kompilierungsfehler können dazu führen, dass der Backend-Container nicht startet.
|
|
|
|
**Lösung:**
|
|
```bash
|
|
# Container-Logs prüfen
|
|
docker logs bizmatch-app --tail 50
|
|
|
|
# Bei TypeScript-Fehlern: Container neu starten
|
|
docker restart bizmatch-app
|
|
|
|
# Prüfen, ob App erfolgreich gestartet ist
|
|
docker logs bizmatch-app | grep "Nest application successfully started"
|
|
```
|
|
|
|
### 6.2 Database Connection Issues
|
|
|
|
**Problem:**
|
|
`password authentication failed for user "bizmatch"`
|
|
|
|
**Lösung:**
|
|
Siehe [README.md - Abschnitt 4.1](README.md#41-password-authentication-failed-for-user-bizmatch)
|
|
|
|
### 6.3 Frontend Proxy-Fehler
|
|
|
|
**Problem:**
|
|
`http proxy error: /bizmatch/select-options` während Backend-Neustart
|
|
|
|
**Lösung:**
|
|
- Warten, bis Backend vollständig gestartet ist (~30 Sekunden)
|
|
- Frontend-Dev-Server bei Bedarf neu starten: `npm start`
|
|
|
|
---
|
|
|
|
## Migration-Guide: JSON-Schema
|
|
|
|
### Von relationaler DB zu JSON-Schema
|
|
|
|
**Beispiel: User-Daten**
|
|
|
|
**Alt (relationale Tabelle):**
|
|
```sql
|
|
CREATE TABLE users (
|
|
id UUID PRIMARY KEY,
|
|
email VARCHAR(255),
|
|
firstname VARCHAR(100),
|
|
lastname VARCHAR(100),
|
|
phone VARCHAR(50),
|
|
...
|
|
);
|
|
```
|
|
|
|
**Neu (JSON-Schema):**
|
|
```sql
|
|
CREATE TABLE users_json (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
email VARCHAR(255),
|
|
data JSONB
|
|
);
|
|
```
|
|
|
|
**JSON-Struktur in `data`-Spalte:**
|
|
```json
|
|
{
|
|
"firstname": "John",
|
|
"lastname": "Doe",
|
|
"email": "john.doe@example.com",
|
|
"phone": "+1-555-0123",
|
|
"customerType": "professional",
|
|
"customerSubType": "broker",
|
|
"location": {
|
|
"name": "Austin",
|
|
"state": "TX",
|
|
"latitude": 30.2672,
|
|
"longitude": -97.7431
|
|
},
|
|
"showInDirectory": true,
|
|
"created": "2025-11-25T10:30:00Z",
|
|
"updated": "2025-11-25T10:30:00Z"
|
|
}
|
|
```
|
|
|
|
**Query-Beispiele:**
|
|
|
|
```sql
|
|
-- Alle Professionals in Texas finden
|
|
SELECT * FROM users_json
|
|
WHERE (data->>'customerType') = 'professional'
|
|
AND (data->'location'->>'state') = 'TX';
|
|
|
|
-- Nach Name suchen
|
|
SELECT * FROM users_json
|
|
WHERE (data->>'firstname') ILIKE '%John%';
|
|
|
|
-- Radius-Suche (50 Meilen um Austin)
|
|
SELECT * FROM users_json
|
|
WHERE (
|
|
3959 * 2 * ASIN(SQRT(
|
|
POWER(SIN((30.2672 - (data->'location'->>'latitude')::float) * PI() / 180 / 2), 2) +
|
|
COS(30.2672 * PI() / 180) * COS((data->'location'->>'latitude')::float * PI() / 180) *
|
|
POWER(SIN((-97.7431 - (data->'location'->>'longitude')::float) * PI() / 180 / 2), 2)
|
|
))
|
|
) <= 50;
|
|
```
|
|
|
|
---
|
|
|
|
## Support & Fragen
|
|
|
|
Bei Fragen zu diesen Änderungen:
|
|
1. README.md für Setup-Informationen konsultieren
|
|
2. Docker-Logs prüfen: `docker logs bizmatch-app` und `docker logs bizmatchdb`
|
|
3. Git-History für Details zu Änderungen durchsuchen
|
|
|
|
**Letzte Aktualisierung:** November 2025
|