- Admin fees yearly view now shows all active companies (including child brands)
- Child brand rows are indented with striped month cells and "firma córka" badge
- Parent companies show expandable brand list, Stawka column with 200/300 zł logic
- Expected fee per month computed from number of active child brands
- Rate change month shown when brand joins mid-year (e.g. "I-III: 200 zł / od IV: 300 zł")
- Sorting groups children directly under their parent
- Reminder logic skipped for child companies
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Legacy private_messages and group_messages are no longer used.
Badge now only counts from conv_messages table.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Shows expected fee per company (200 zł for 1 brand, 300 zł for 2+)
- Child companies shown with striped "nie dotyczy" tiles
- Rate change month displayed (e.g., "I-III: 200 zł, od IV: 300 zł")
- Expandable brand list under parent company name
- Children grouped after their parent in the table
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add sort keys and data-sort-value attributes to 'Upr. firmowe' and 'Rola' columns
- Add filter tabs for MANAGER, OFFICE_MANAGER, company-role NONE and MANAGER
- Add data-company-role attribute to user rows for JS filtering
- Grant OFFICE_MANAGER access to admin_users, assign-company, reset-password, change-role, get-roles endpoints
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The badge endpoint api_unread_count only counted legacy private_messages
and group_messages. Now also counts unread conv_messages from the new
conversations system, fixing phantom unread counts for users.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace company_id from current_user with active company from session in
the colleagues API endpoint, and autofill guest org from active_company.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Users with multiple companies now see a dropdown to choose which company
a B2B classified ad is posted for. Single-company users get a hidden field.
Server-side validates the selected company_id against user's actual memberships.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add helpers/company_context.py with get_active_company_id() fallback logic
- Add inject_company_context() context processor to app.py (user_companies, active_company, has_multiple_companies)
- Add /api/switch-company/<id> POST endpoint in public blueprint
- Set session['active_company_id'] on login (both standard and 2FA paths)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace textarea with Quill editor in new/edit classified forms
- Sanitize HTML with sanitize_html() on save (XSS prevention)
- Render HTML in classified detail view, strip tags in list view
- New script: classified_expiry_notifier.py sends email 3 days before
expiry with link to extend. Run daily via cron at 8:00.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Added to GeoIP tab:
- Last 20 blocked requests with IP, country, path, timestamp
- Top 10 most targeted URL paths with hit counts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Expired classifieds show 'Wygasło' badge on list and detail view
- Closed classifieds show 'Zamknięte' badge on list
- Author can extend by 30 days with one click
- Homepage 'Nowe na portalu' excludes expired classifieds
- List shows all classifieds, active first
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
updated_at now refreshes on: edit, new Q&A question, new Q&A answer.
Does NOT refresh on: page views, interest clicks, close.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Removed onupdate from Classified.updated_at, set it manually in edit route.
Ensures toggle_interest, close, and views don't alter the date.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use raw SQL UPDATE for views_count to bypass SQLAlchemy onupdate.
Restore updated_at display in homepage cards - now accurate.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
updated_at was being triggered by views_count increment on every page
view, making dates misleading. Reverted to created_at for display and sort.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Forum cards now show date of latest reply (not topic creation).
B2B cards show updated_at (not created_at), sorted by most recent activity.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace 'Najnowszy wpis na forum' (duplicate with Nowe na portalu)
with 'Nowi użytkownicy portalu' showing 4 latest registered users
with avatars, names, dates and company names.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shows 2 latest forum topics + 2 latest B2B classifieds in a 4-column
grid between events and NordaGPT banner. Responsive 2-col on mobile.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New edit route with form pre-filled with existing data
- Edit existing attachments (mark for deletion) + add new ones
- Edit button visible to classified author on detail view
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New ClassifiedAttachment model with migration
- FileUploadService extended with 'classified' type
- Dropzone with drag & drop, paste, multi-file preview in creation form
- Image gallery with lightbox in classified detail view
- Max 10 files, 5MB each, JPG/PNG/GIF
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three new notification types:
- New question → author gets in-app + email
- Answer to question → questioner gets in-app + email
- Someone interested → author gets in-app only
Previously the B2B board had zero notifications, so authors never
knew someone asked a question about their listing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The interest endpoint was returning 400 because fetch sent
Content-Type:application/json with an empty body, causing Flask
to fail JSON parsing. Removed the header since no JSON body is
sent. Also reverted unnecessary CSRF blueprint exemption.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
csrf.exempt on the full classifieds blueprint during registration,
same pattern as API blueprint. All classifieds endpoints are behind
@login_required + @member_required so CSRF exemption is safe.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The /tablica/<id>/interest AJAX POST was returning 400 because
Flask-WTF CSRF validation rejected the token despite X-CSRFToken
header being present. Endpoint is protected by @login_required
and @member_required, so CSRF exemption is safe.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MessageUploadService.__init__() requires app_root but was called
without arguments, causing send_message errors and double-sending
due to JS retry. Now uses current_app.root_path.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
Email notifications for forum replies were linking to /forum/ID
without the #reply-XX anchor. Now includes reply_id in the URL
so the email "Zobacz odpowiedź" button scrolls directly to the
new reply instead of the top of the topic.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New /admin/roadmap page showing feature requests from members in
three columns: Planned, In Progress, Done. Cards expand on click
to show implementation details. First item: multi-location support
requested by Daniel Kochański (Stalpunkt).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
JDG companies don't have board members or shareholders. When CEIDG
returns data for a company, automatically remove company_people
records sourced from ekrs.ms.gov.pl.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When fetching company data by NIP, check CEIDG first (JDG) before
trying Biała Lista/KRS. This prevents JDG companies from being
overwritten with spółka data. Also auto-clears KRS fields when
CEIDG confirms the company is a JDG.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Renumbered all versions from v1.53+ down by 1 to eliminate the
v1.51→v1.53 gap. Current latest: v1.62.0.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Link keys must match the <strong>title</strong> text exactly for the
template macro to render "Wypróbuj →" buttons next to each item.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Merged same-day releases into v1.57.0. Renumbered v1.58-v1.63.
Added links to homepage and other key pages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New features: company wizard, paid events, homepage redesign, new members
page, group messaging UI, recipient search, group management panel.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New PATCH /api/conversations/<id>/members/<uid> endpoint for role changes
- Owner can promote members to admin and demote back to member
- Admin can add/remove members and edit group name (same as owner except role changes)
- Member list shows role labels (Właściciel/Administrator/Członek)
- Fix: state.currentConversation → state.currentConversationId (panel was empty)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When composing a new message to someone you already have a conversation
with, the dedup logic returned the existing conversation without adding
the message. Now it creates the message and publishes SSE notification.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The compose button was just a small pencil icon with no label. Now it shows
"Nowa wiadomość" text (hidden on mobile). Recipient search was broken because
window.__USERS__ was always empty — replaced with /api/users/search API endpoint
that queries active users by name/email with autocomplete suggestions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Event attendee counts were inconsistent - event detail page showed total
(members + guests = 42) but event list and homepage showed only members (39).
Now all views use total_attendee_count including guests (osoby towarzyszące).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Logo images were cached for 30 days by nginx. After selecting a new logo
from the gallery, the browser still showed the old/placeholder image.
- Add cache-bust query param (?v=timestamp) to logo <img> src
- Update company.last_updated when logo is confirmed
- Use Date.now() redirect instead of reload() after confirm
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Flash success message showing format conversion (e.g. "JPG do WebP")
- Flash error message if conversion fails with suggestion to try another file
- Flash warning for unsupported file formats
- Form hint explains automatic WebP conversion
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Templates expect logo at {slug}.webp with SVG fallback. When users uploaded
JPG/PNG files, the logo was saved with original extension and never displayed.
Now all raster uploads are converted to .webp via Pillow; SVG stays as-is.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Route GET/POST /admin/kalendarz/<id>/edytuj
- Reuses admin_new.html template with pre-filled fields in edit mode
- Edit button on event detail page and admin calendar list
- Supports all fields including paid event settings and attachments
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- EventGuest.guest_type: 'member' (member rate) or 'external' (guest rate)
- Dropdown of company colleagues when adding member-type guest
- Manual entry option for members not on portal
- Admin payment panel: "Dodaj osobę" with "Dodaj + opłacone" shortcut
- Migration 064: guest_type column
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add is_paid, price_member, price_guest to NordaEvent. Add payment_status,
payment_amount, payment_confirmed_by/at to EventAttendee and EventGuest.
Auto-assign amounts on RSVP. Admin panel at /admin/kalendarz/<id>/platnosci
for OFFICE_MANAGER to confirm payments. User sees payment status on event page.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>