From 89b8f7537545dcbc8fcfb02448865b5f055f67ae Mon Sep 17 00:00:00 2001 From: Floke Date: Fri, 9 Jan 2026 10:18:45 +0000 Subject: [PATCH] Docs: Update MIGRATION_PLAN.md to v0.4.0 with new features (Company Explorer) --- MIGRATION_PLAN.md | 46 ++++++- company-explorer/backend/app.py | 39 ++++++ company-explorer/backend/config.py | 2 +- company-explorer/frontend/src/App.tsx | 2 +- .../frontend/src/components/Inspector.tsx | 123 +++++++++++++----- 5 files changed, 179 insertions(+), 33 deletions(-) diff --git a/MIGRATION_PLAN.md b/MIGRATION_PLAN.md index eedb7711..ac79355c 100644 --- a/MIGRATION_PLAN.md +++ b/MIGRATION_PLAN.md @@ -1,4 +1,4 @@ -# Migrations-Plan: Legacy GSheets -> Company Explorer (Robotics Edition) +# Migrations-Plan: Legacy GSheets -> Company Explorer (Robotics Edition v0.4.0) **Kontext:** Neuanfang für die Branche **Robotik & Facility Management**. **Ziel:** Ablösung von Google Sheets/CLI durch eine Web-App ("Company Explorer") mit SQLite-Backend. @@ -77,4 +77,46 @@ Wir kapseln das neue Projekt vollständig ab ("Fork & Clean"). 2. **Setup:** Init `company-explorer` (Backend + Frontend Skeleton). 3. **Foundation:** DB-Schema + "List Matcher" (Deduplizierung ist Prio A für Operations). 4. **Enrichment:** Implementierung des Scrapers + Signal Detector (Robotics). -5. **UI:** React Interface für die Daten. \ No newline at end of file +5. **UI:** React Interface für die Daten. + +## 7. Historie & Fixes (Jan 2026) + +* **[UPGRADE] v0.4.0: Export & Manual Impressum** + * **JSON Export:** Erweiterung der Detailansicht um einen "Export JSON"-Button, der alle Unternehmensdaten (inkl. Anreicherungen und Signale) herunterlädt. + * **Zeitstempel:** Anzeige des Erstellungsdatums für jeden Anreicherungsdatensatz (Wikipedia, AI Dossier, Impressum) in der Detailansicht. + * **Manuelle Impressum-URL:** Möglichkeit zur manuellen Eingabe einer Impressum-URL in der Detailansicht, um die Extraktion von Firmendaten zu erzwingen. + * **Frontend-Fix:** Behebung eines Build-Fehlers (`Unexpected token`) in `Inspector.tsx` durch Entfernung eines duplizierten JSX-Blocks. + +* **[UPGRADE] v2.6.2: Report Completeness & Edit Mode** + * **Edit Hard Facts:** Neue Funktion in Phase 1 ("Edit Raw Data") erlaubt die manuelle Korrektur der extrahierten technischen JSON-Daten. + * **Report-Update:** Phase 5 Prompt wurde angepasst, um explizit die Ergebnisse aus Phase 2 (ICPs & Data Proxies) im finalen Report aufzuführen. + * **Backend-Fix:** Korrektur eines Fehlers beim Speichern von JSON-Daten, der auftrat, wenn Datenbank-Inhalte als Strings vorlagen. + +* **[UPGRADE] v2.6.1: Stability & UI Improvements** + * **White Screen Fix:** Robuste Absicherung des Frontends gegen `undefined`-Werte beim Laden älterer Sitzungen (`optional chaining`). + * **Session Browser:** Komplettes Redesign der Sitzungsübersicht zu einer übersichtlichen Listenansicht mit Icons (Reinigung/Service/Transport/Security). + * **URL-Anzeige:** Die Quell-URL wird nun als dedizierter Link angezeigt und das Projekt automatisch basierend auf dem erkannten Produktnamen umbenannt. + +* **[UPGRADE] v2.6: Rich Session Browser** + * **Neues UI:** Die textbasierte Liste für "Letzte Sitzungen" wurde durch eine dedizierte, kartenbasierte UI (`SessionBrowser.tsx`) ersetzt. + * **Angereicherte Daten:** Jede Sitzungskarte zeigt nun den Produktnamen, die Produktkategorie (mit Icon), eine Kurzbeschreibung und einen Thumbnail-Platzhalter an. + * **Backend-Anpassung:** Die Datenbankabfrage (`gtm_db_manager.py`) wurde erweitert, um diese Metadaten direkt aus der JSON-Spalte zu extrahieren und an das Frontend zu liefern. + * **Verbesserte UX:** Deutlich verbesserte Übersichtlichkeit und schnellere Identifikation von vergangenen Analysen. + +* **[UPGRADE] v2.5: Hard Fact Extraction** + * **Phase 1 Erweiterung:** Implementierung eines sekundären Extraktions-Schritts für "Hard Facts" (Specs). + * **Strukturiertes Daten-Schema:** Integration von `templates/json_struktur_roboplanet.txt`. + * **Normalisierung:** Automatische Standardisierung von Einheiten (Minuten, cm, kg, m²/h). + * **Frontend Update:** Neue UI-Komponente zur Anzeige der technischen Daten (Core Data, Layer, Extended Features). + * **Sidebar & Header:** Update auf "ROBOPLANET v2.5". + +* **[UPGRADE] v2.4:** + * Dokumentation der Kern-Engine (`helpers.py`) mit Dual SDK & Hybrid Image Generation. + * Aktualisierung der Architektur-Übersicht und Komponenten-Beschreibungen. + * Versionierung an den aktuellen Code-Stand (`v2.4.0`) angepasst. + +* **[UPGRADE] v2.3:** + * Einführung der Session History (Datenbank-basiert). + * Implementierung von Markdown-Cleaning (Stripping von Code-Blocks). + * Prompt-Optimierung für tabellarische Markdown-Ausgaben in Phase 5. + * Markdown-File Import Feature. \ No newline at end of file diff --git a/company-explorer/backend/app.py b/company-explorer/backend/app.py index cfe0e68c..bab356f2 100644 --- a/company-explorer/backend/app.py +++ b/company-explorer/backend/app.py @@ -261,6 +261,45 @@ def override_website_url(company_id: int, url: str = Query(...), db: Session = D db.commit() return {"status": "updated", "website": url} +@app.post("/api/companies/{company_id}/override/impressum") +def override_impressum_url(company_id: int, url: str = Query(...), db: Session = Depends(get_db)): + """ + Manually sets the Impressum URL for a company and triggers re-extraction. + """ + company = db.query(Company).filter(Company.id == company_id).first() + if not company: + raise HTTPException(404, "Company not found") + + logger.info(f"Manual Override for {company.name}: Setting Impressum URL to {url}") + + # 1. Scrape Impressum immediately + impressum_data = scraper._scrape_impressum_data(url) + if not impressum_data: + raise HTTPException(status_code=400, detail="Failed to extract data from provided URL") + + # 2. Find existing scrape data or create new + existing_scrape = db.query(EnrichmentData).filter( + EnrichmentData.company_id == company.id, + EnrichmentData.source_type == "website_scrape" + ).first() + + if not existing_scrape: + # Create minimal scrape entry + db.add(EnrichmentData( + company_id=company.id, + source_type="website_scrape", + content={"impressum": impressum_data, "text": "", "title": "Manual Impressum", "url": url} + )) + else: + # Update existing + content = dict(existing_scrape.content) if existing_scrape.content else {} + content["impressum"] = impressum_data + existing_scrape.content = content + existing_scrape.updated_at = datetime.utcnow() + + db.commit() + return {"status": "updated", "data": impressum_data} + def run_discovery_task(company_id: int): # New Session for Background Task from .database import SessionLocal diff --git a/company-explorer/backend/config.py b/company-explorer/backend/config.py index 2d66b4c6..6fb6de9a 100644 --- a/company-explorer/backend/config.py +++ b/company-explorer/backend/config.py @@ -9,7 +9,7 @@ try: class Settings(BaseSettings): # App Info APP_NAME: str = "Company Explorer" - VERSION: str = "0.3.0" + VERSION: str = "0.4.0" DEBUG: bool = True # Database (Store in App dir for simplicity) diff --git a/company-explorer/frontend/src/App.tsx b/company-explorer/frontend/src/App.tsx index 897a7532..925bb942 100644 --- a/company-explorer/frontend/src/App.tsx +++ b/company-explorer/frontend/src/App.tsx @@ -73,7 +73,7 @@ function App() {

Company Explorer

-

ROBOTICS EDITION v0.3.0 (Polling & Legal Data)

+

ROBOTICS EDITION v0.4.0 (Overwrites & Export)

diff --git a/company-explorer/frontend/src/components/Inspector.tsx b/company-explorer/frontend/src/components/Inspector.tsx index 5e9e146b..417564c8 100644 --- a/company-explorer/frontend/src/components/Inspector.tsx +++ b/company-explorer/frontend/src/components/Inspector.tsx @@ -55,6 +55,8 @@ export function Inspector({ companyId, onClose, apiBase }: InspectorProps) { const [wikiUrlInput, setWikiUrlInput] = useState("") const [isEditingWebsite, setIsEditingWebsite] = useState(false) const [websiteInput, setWebsiteInput] = useState("") + const [isEditingImpressum, setIsEditingImpressum] = useState(false) + const [impressumUrlInput, setImpressumUrlInput] = useState("") const fetchData = (silent = false) => { if (!companyId) return @@ -84,6 +86,7 @@ export function Inspector({ companyId, onClose, apiBase }: InspectorProps) { fetchData() setIsEditingWiki(false) setIsEditingWebsite(false) + setIsEditingImpressum(false) setIsProcessing(false) // Reset on ID change }, [companyId]) @@ -173,6 +176,21 @@ export function Inspector({ companyId, onClose, apiBase }: InspectorProps) { } } + const handleImpressumOverride = async () => { + if (!companyId) return + setIsProcessing(true) + try { + await axios.post(`${apiBase}/companies/${companyId}/override/impressum?url=${encodeURIComponent(impressumUrlInput)}`) + setIsEditingImpressum(false) + fetchData() + } catch (e) { + alert("Impressum update failed") + console.error(e) + } finally { + setIsProcessing(false) + } + } + if (!companyId) return null const wikiEntry = data?.enrichment_data?.find(e => e.source_type === 'wikipedia') @@ -304,43 +322,90 @@ export function Inspector({ companyId, onClose, apiBase }: InspectorProps) {
{/* Impressum / Legal Data (NEW) */} - {impressum && ( -
-
-
-
- -
- Official Legal Data +
+
+
+
+
+ Official Legal Data +
+
{scrapeDate && (
{new Date(scrapeDate).toLocaleDateString()}
)} + {!isEditingImpressum ? ( + + ) : ( +
+ + +
+ )}
- -
- {impressum.legal_name || "Unknown Legal Name"} -
- -
- -
-
{impressum.street}
-
{impressum.zip} {impressum.city}
-
-
- - {(impressum.email || impressum.phone) && ( -
- {impressum.email && {impressum.email}} - {impressum.phone && {impressum.phone}} - {impressum.vat_id && VAT: {impressum.vat_id}} -
- )}
- )} + + {isEditingImpressum && ( +
+ setImpressumUrlInput(e.target.value)} + placeholder="https://.../impressum" + className="w-full bg-slate-900 border border-slate-700 rounded px-2 py-1 text-xs text-white focus:ring-1 focus:ring-blue-500 outline-none" + autoFocus + /> +
+ )} + + {impressum ? ( + <> +
+ {impressum.legal_name || "Unknown Legal Name"} +
+ +
+ +
+
{impressum.street}
+
{impressum.zip} {impressum.city}
+
+
+ + {(impressum.email || impressum.phone) && ( +
+ {impressum.email && {impressum.email}} + {impressum.phone && {impressum.phone}} + {impressum.vat_id && VAT: {impressum.vat_id}} +
+ )} + + ) : !isEditingImpressum && ( +
+ No legal data found. Click pencil to provide direct Impressum link. +
+ )} +
+ + {/* AI Analysis Dossier (NEW) */} {aiAnalysis && (