Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
New roadmap item: automated procurement/tender aggregation from BIP, e-Zamówienia, TED, municipal websites. Requested by Daniel Kochański (Stalpunkt). Priority: high. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
139 lines
6.4 KiB
Python
139 lines
6.4 KiB
Python
"""
|
|
Admin Roadmap Routes
|
|
====================
|
|
|
|
Product roadmap — feature requests from members and strategic plans.
|
|
"""
|
|
|
|
import logging
|
|
from flask import render_template
|
|
from flask_login import login_required
|
|
from . import bp
|
|
from database import SystemRole
|
|
from utils.decorators import role_required
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
ROADMAP_ITEMS = [
|
|
{
|
|
'id': 1,
|
|
'title': 'Wiele lokalizacji firmy na mapie',
|
|
'description': 'Firmy z kilkoma oddziałami/punktami mogą dodać wiele adresów. '
|
|
'Każdy wyświetlany na profilu z linkiem do Google Maps.',
|
|
'details': [
|
|
'<strong>1. Model</strong> — nowa tabela <code>company_locations</code>: id, company_id (FK CASCADE), '
|
|
'label (np. "Biuro główne", "Magazyn"), address_street, address_city, address_postal, '
|
|
'lat, lng (opcjonalne — na przyszłość), is_primary, source, created_at. '
|
|
'Relacja na Company: locations = relationship(CompanyLocation, cascade=all delete-orphan)',
|
|
|
|
'<strong>2. Migracja SQL</strong> — <code>database/migrations/100_company_locations.sql</code>: '
|
|
'CREATE TABLE IF NOT EXISTS, indeks na company_id, GRANT na nordabiz_app. '
|
|
'Migracja danych: INSERT z istniejących address_* dla firm z adresem (żeby nie stracić danych)',
|
|
|
|
'<strong>3. Formularz edycji</strong> — nowa sekcja "Dodatkowe lokalizacje" w zakładce Kontakt '
|
|
'(<code>templates/company_edit.html</code>). Dynamiczne wiersze wzorowane na CompanyWebsite: '
|
|
'label + street + postal + city + is_primary radio + przycisk usuń. Max 10 lokalizacji. '
|
|
'JS: makeLocationRow(), removeLocationRow(), reindexLocationRadios()',
|
|
|
|
'<strong>4. Zapis</strong> — funkcja <code>_save_locations()</code> w '
|
|
'<code>blueprints/public/routes_company_edit.py</code>. '
|
|
'Strategia delete-and-reinsert (jak websites): usuń wszystkie WHERE company_id AND source IN (null, manual_edit), '
|
|
'wstaw z formularza: location_labels[], location_streets[], location_postals[], location_cities[], location_primary. '
|
|
'Aktualizacja address_* na Company z primary location',
|
|
|
|
'<strong>5. Profil firmy</strong> — wyświetlanie w <code>templates/company_detail.html</code> (linia ~1078). '
|
|
'Jeśli firma ma lokalizacje → wyświetl wszystkie z labelami, każda z linkiem "Pokaż na mapie →" '
|
|
'(Google Maps Search URL). Primary oznaczona jako "Siedziba główna". '
|
|
'Fallback na obecny address_full jeśli brak lokalizacji',
|
|
|
|
'<strong>6. Route</strong> — w <code>blueprints/public/routes.py</code> company_detail(): '
|
|
'eager load company.locations i przekazać do szablonu',
|
|
|
|
'<strong>Czego NIE robimy:</strong> brak embedded Google Maps (iframe/API), '
|
|
'brak geocodingu (lat/lng pola przygotowane na przyszłość), '
|
|
'brak edycji lokalizacji przez admina — tylko przez właściciela firmy',
|
|
],
|
|
'requested_by': 'Daniel Kochański (Stalpunkt)',
|
|
'date': '2026-04-09',
|
|
'priority': 'medium',
|
|
'status': 'planned',
|
|
'category': 'feature',
|
|
},
|
|
{
|
|
'id': 2,
|
|
'title': 'Agregator przetargów publicznych',
|
|
'description': 'Automatyczne pobieranie przetargów z portali publicznych '
|
|
'(BIP, e-Zamówienia, TED, strony urzędów miast/gmin, spółki miejskie) '
|
|
'i wyświetlanie na portalu z możliwością filtrowania wg branży.',
|
|
'details': [
|
|
'<strong>1. Źródła danych</strong> — BIP (scraping RSS/HTML), e-Zamówienia (API publiczne), '
|
|
'TED/Tenders Electronic Daily (API EU), strony urzędów miast i gmin (scraping), spółki miejskie',
|
|
|
|
'<strong>2. Model danych</strong> — nowa tabela <code>public_tenders</code>: id, title, description, '
|
|
'source (bip/ezamowienia/ted/municipal), source_url, published_at, deadline, '
|
|
'value_estimate, category/tags, location, status (active/expired), fetched_at',
|
|
|
|
'<strong>3. Cron/scheduler</strong> — cykliczne pobieranie (np. co 4h), deduplikacja po source_url, '
|
|
'parsowanie i kategoryzowanie treści przez AI (dopasowanie do branż firm w Izbie)',
|
|
|
|
'<strong>4. Panel użytkownika</strong> — nowa zakładka "Przetargi" z filtrowaniem: '
|
|
'branża, lokalizacja, wartość, termin składania, źródło. Subskrypcja powiadomień wg filtrów',
|
|
|
|
'<strong>5. Integracja z NordaGPT</strong> — chatbot może wyszukiwać przetargi pasujące '
|
|
'do profilu firmy użytkownika i proaktywnie sugerować nowe ogłoszenia',
|
|
|
|
'<strong>6. Powiadomienia</strong> — email/in-app alert gdy pojawi się przetarg pasujący '
|
|
'do zapisanych filtrów użytkownika lub profilu firmy',
|
|
|
|
'<strong>Ryzyka:</strong> scraping BIP/urzędów jest kruchy (zmienne layouty), '
|
|
'e-Zamówienia API może wymagać rejestracji, TED API wymaga klucza UE. '
|
|
'Rekomendacja: zacząć od e-Zamówienia (najstabilniejsze API)',
|
|
],
|
|
'requested_by': 'Daniel Kochański (Stalpunkt)',
|
|
'date': '2026-04-09',
|
|
'priority': 'high',
|
|
'status': 'planned',
|
|
'category': 'feature',
|
|
},
|
|
]
|
|
|
|
STATUS_LABELS = {
|
|
'planned': ('Planowane', '#6366f1'),
|
|
'in_progress': ('W trakcie', '#f59e0b'),
|
|
'done': ('Zrealizowane', '#10b981'),
|
|
'on_hold': ('Wstrzymane', '#94a3b8'),
|
|
}
|
|
|
|
PRIORITY_LABELS = {
|
|
'high': ('Wysoki', '#ef4444'),
|
|
'medium': ('Średni', '#f59e0b'),
|
|
'low': ('Niski', '#6b7280'),
|
|
}
|
|
|
|
CATEGORY_LABELS = {
|
|
'feature': 'Nowa funkcjonalność',
|
|
'improvement': 'Ulepszenie',
|
|
'bugfix': 'Naprawa błędu',
|
|
}
|
|
|
|
|
|
@bp.route('/roadmap')
|
|
@login_required
|
|
@role_required(SystemRole.ADMIN)
|
|
def admin_roadmap():
|
|
"""Product roadmap — feature requests and development plans."""
|
|
planned = [i for i in ROADMAP_ITEMS if i['status'] == 'planned']
|
|
in_progress = [i for i in ROADMAP_ITEMS if i['status'] == 'in_progress']
|
|
done = [i for i in ROADMAP_ITEMS if i['status'] == 'done']
|
|
|
|
return render_template(
|
|
'admin/roadmap.html',
|
|
planned=planned,
|
|
in_progress=in_progress,
|
|
done=done,
|
|
status_labels=STATUS_LABELS,
|
|
priority_labels=PRIORITY_LABELS,
|
|
category_labels=CATEGORY_LABELS,
|
|
)
|