img.get('class') can return an empty list [], causing IndexError
when accessing [0]. Added `or ['']` fallback.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The script was calling /firma?nip=X (wrong endpoint) instead of using
fetch_ceidg_by_nip() which does two-phase /firmy?nip=X then /firma/{id}.
Now uses the same service and field mapping as the admin panel button.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The script was calling auditor.audit_company() but not auditor.save_audit_result(),
causing profiles to be found but never persisted to the database.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- GBP: access .completeness_score attribute + call save_audit()
- Social: count saved DB records instead of parsing audit result dict
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- KRS: search_by_nip() returns dict, not just KRS number
- SEO: SEOAuditor(database_url) + audit_company(company_dict)
- Social: SocialMediaAuditor() + audit_company(company_dict)
- GBP: GBPAuditService(db) + audit_company(company_id)
- Support multiple company IDs in one invocation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allows running the same enrichment workflow as the "Uzbrój firmę" button
directly from the command line, without needing browser/admin login.
Usage: python3 scripts/arm_company.py <company_id> [--force]
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two buttons side by side: "Uzbrój firmę" runs only missing steps,
"Zaktualizuj dane" forces re-run of all steps regardless of status.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The logo path was hardcoded to .webp even when the actual file was .svg,
causing broken image display for SVG logos like Orlex Design.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Logo check only looked for .webp files, missing SVG logos like
Orlex Design. Now checks both extensions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When "Uzbrój firmę" runs automatically, logo step now picks the
recommended candidate instead of showing the gallery (which would
be overwritten by page reload). Manual "Szukaj logo" still shows
the gallery for admin selection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move logo selection to step 5 (last), reorder: registry, SEO, social,
GBP, logo. After clicking "Szukaj logo", admin sees thumbnail gallery
of candidates and can pick the best one or cancel.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each workflow action card now shows a numbered badge (1-5) indicating
the recommended execution order for administrators.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CEIDG enrichment now creates individual CompanyPKD records from the PKD
list, matching the pattern used by KRS enrichment for consistency.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
KRS API returns two date formats for za_okres field:
"01.01.2011 - 31.12.2011" (older) and "OD 01.01.2013 DO 31.12.2013" (newer).
Use regex to extract all date patterns instead of splitting on ' - '.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Map remaining KRS API fields: registration date, company agreement date,
duration, capital currency, OPP status, representation rules, shareholders
(wspólnicy), and financial reports (sprawozdania finansowe).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
KRS API returns kontakt_krs with www and email fields. These were not
being mapped to Company.website and Company.email. Now enrichment
extracts these and normalizes the URL (adds https:// prefix, lowercase).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The KRS enrichment function was only mapping forma_prawna, legal_name
and capital. Now maps REGON, address (ulica + nr_domu), city, postal,
primary PKD code on Company model, and NIP if missing. Fixed field
name mismatches: nr_domu (not numer), opis (not nazwa), glowna (not
glowny). City names are title-cased from KRS uppercase format.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Individual action buttons now reload the page after 1.5s to reflect
updated data and status indicators. The master "Uzbrój firmę" workflow
skips per-step reload and only reloads once after all steps complete.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New admin page at /admin/companies/{id}/detail showing company data,
completeness score, and action buttons for registry data (CEIDG/KRS),
logo fetch, SEO audit, social media audit, and GBP audit.
Includes "Uzbrój firmę" master button for sequential execution.
Company list now links to detail page with "NOWA" badge for recent entries.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PDF files: "Otwórz" (inline in browser) + "Pobierz" (download)
DOCX files: "Pobierz" only (browsers can't display DOCX inline)
Removes LibreOffice on-the-fly conversion - simpler and more reliable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use /usr/bin/libreoffice (Gunicorn has limited PATH)
- Set HOME=/tmp (LibreOffice needs writable home dir)
- Handle FileNotFoundError with user-friendly message
- Improve error flash messages in Polish
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DOCX/DOC documents are now converted to PDF using LibreOffice headless
when the user clicks "Otwórz". The converted PDF is cached next to the
original file so subsequent views are instant.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PDF documents now have an "Otwórz" button that opens
the file in the browser's built-in PDF viewer.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DocumentUploadService.get_file_path() resolves paths using uploaded_at,
so import scripts must store files in directories matching that date.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add document management routes (upload, download, soft-delete) to board blueprint,
link BoardDocument to BoardMeeting via meeting_id FK, add documents section to
meeting view template, and include import scripts for meeting 2/2026 data and PDFs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sections now have collapsible headers with localStorage persistence.
Layout order: FB page stats > Analityka (charts) > Top 5 > App posts > FB posts.
Each section can be independently expanded/collapsed by clicking the header.
Collapse state persists across page loads via localStorage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
perPage=0 (show all) was being overridden to 10 by || operator.
Changed to explicit key-in-object check to preserve 0 value.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
renderFbPosts no longer unconditionally resets page to 1.
Only resets when dataset size changes (new data loaded).
Preserves user's dropdown selection during auto-load.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Default 10 posts per page with dropdown (10/20/50/100/Wszystkie).
"Pokaż więcej" button loads next page incrementally.
Pagination bar shows count and controls at bottom of posts list.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added 200px fixed height container and maintainAspectRatio:false
to "Typy postów" doughnut chart so second row matches first row height.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaced ASCII Polish strings with proper diacritics: postow→postów,
Odswiez→Odśwież, Sredni→Średni, Blad→Błąd, Ladowanie→Ładowanie,
Nastepna→Następna, Usun→Usuń, Utworz→Utwórz, and ~30 more.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Removed redundant Analityka button since charts auto-load on page load.
"Odswiez wszystkie" now also renders charts after fetching.
Two buttons remain: "Najnowsze 10" (quick preview) and "Odswiez wszystkie"
(full fetch + cache + charts).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Charts now render automatically on page load via AJAX from DB cache
(no click needed). Info bar above charts shows post count, cache date,
and hint to refresh. GET cache endpoint now returns cached_at date.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Facebook Graph API can return cycling cursors causing infinite fetch loops.
Added: post ID deduplication, seen-cursor detection, max 100 pages limit.
Applied to both loadAllFbPosts and refreshAllFbPosts functions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shows clear instructions: if cache has more posts than displayed,
guide to Analityka. If cache is small (10 posts), guide to
"Odswiez wszystkie" first, then Analityka.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
"Najnowsze 10" no longer saves to DB cache.
New "Odswiez wszystkie" button fetches all posts via FB API pagination
and saves to cache. "Analityka" uses cache for instant charts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixes slow page load for non-admin users (919KB inline JSON).
Route now sends max 10 posts inline with total_count metadata.
New GET endpoint serves full cache via AJAX for Analityka button.
loadAllFbPosts tries DB cache first (instant), falls back to FB API.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Admin's _get_user_company_ids returns None meaning all companies,
but iterating over None gave empty list. Now falls back to fb_stats keys.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Migration 071: Add cached_posts (JSONB) and posts_cached_at to social_media_config
- Service: get_cached_posts() and save_all_posts_to_cache() methods
- Route: New POST endpoint to save posts cache, pass cached data to template
- Template: Render cached posts+charts instantly on page load from DB,
save to DB after "Load all" or "Refresh", remove AJAX auto-load
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Posts now appear immediately when visiting Social Media Dashboard
instead of requiring manual button click.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shortened nav label to fit single line, added rotated gradient beta badge.
Moved nav position from after Edukacja to between Forum and Aktualnosci.
Updated admin sidebar label to Social Dashboard with beta badge.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>