- Remove /register route and nav links (users created via Evotor webhook)
- Fix evotor_webhooks.py: use phone=None instead of phone="" to avoid unique constraint
- Add admin "view as user" feature: POST /admin/users/{id}/view-as sets viewed_user_id
in session; POST /admin/view-as/stop clears it
- catalog, vk_catalog, sync, connections GET routes use get_viewed_user() so admins
see another user's data while browsing
- Orange banner shown at top when admin is viewing as another user
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Added store_filters_seeded / group_filters_seeded flags to SyncConfig.
_enabled_*_ids now returns None (all enabled) only before first toggle,
not when the filter table is empty due to all being disabled.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Phone is optional — admin users created via script don't have one.
Added migration 0010 to alter the column, updated create_admin.py to
pass None instead of empty string.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds evo_mirror_enabled and vk_mirror_enabled flags to SyncConfig.
Each of the three background tasks (Зеркало Эвотор / Зеркало ВК /
Синхронизация) can now be enabled independently from the /sync page.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously only the create path checked allow_to_sell. The update path
kept syncing disabled products indefinitely.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each product's description is now built as "Name (цена за M.)" using its
own measure_name. The global description_postfix setting is removed —
it couldn't handle per-product units.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds price_multiplier and description_postfix to SyncConfig. The sync
page at /sync lets users configure them. vk_sync reads these per-user
settings and applies the multiplier to price and appends the postfix
as "(postfix)" to the VK product description.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
VK Market API expects the price field in rubles (float), not kopecks.
Removing the *100 conversion that was inflating all prices by 100x.
Comparison with cached VK prices now also uses rubles consistently.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add api_logs table (migration 0007) and ApiLog model
- Add web/lib/api_logger.py — httpx wrapper that records every outbound call
- Wire api_logger into vk_sync, vk_catalog, and connections test endpoints
- Add /admin/logs page with filters (service, method, status, time range, URL search) and expandable request/response detail
- Add "Логи" nav link for admin users
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
After refresh_vk_catalog syncs the album list from VK, remove any
VkCachedAlbum rows whose album_id was not returned by the API.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
VK API v5.199 requires item_id not item_ids for market.removeFromAlbum.
The wrong parameter name caused silent failures — products were not
actually removed from their old album when moved to a new one.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- catalog.py: include parent_id as fallback for group_evotor_id (Evotor API returns parent_id instead of group/parentUuid)
- vk_sync.py: on product update, detect album change and call market.removeFromAlbum + market.addToAlbum to move product to the correct album
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add VK OAuth implicit flow: /vk-auth redirect, /vk-callback JS page,
/vk-callback/save endpoint with state validation
- Add VK_CLIENT_ID/VK_CLIENT_SECRET to config
- Add refresh_token/token_expires_at columns to vk_connections (migration 0006)
- Fix vk_catalog task: handle price/thumb_photo as string or dict (VK API v5.199)
- Fix connections/vk/test: use groups.getById instead of market.getAlbums
(works with both user and group tokens)
- Add orphan deletion to mirror_to_vk: VK products not in Evotor are removed
- Handle ungrouped Evotor products: push to "Без категории" VK album
- Respect SyncConfig.is_enabled in mirror_to_vk
- Add product count column to catalog groups page
- Add group name column to catalog products page
- Expand test suite: 73 new tests covering connections routes, catalog routes,
vk_sync task logic, and catalog task helpers (138 total, all passing)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Evotor catalog: background Celery task syncing stores/groups/products
from Evotor API; UI pages with per-store and per-group sync toggles
- VK connection: manual token + group ID entry with inline test button
- Evotor connection: inline test button (calls /stores)
- VK catalog: background task syncing VK Market albums and products;
separate catalog UI at /vk-catalog/albums
- SyncFilter extended to support entity_type=group with parent_entity_id
- Migration 0004: vk_cached_albums + vk_cached_products tables
- Beat schedule updated to run both refresh_catalog and refresh_vk_catalog
- README updated with new schema, routes, tasks, and config
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
FastAPI + Celery + Redis + MariaDB stack with 6-service docker-compose.
Includes project skeleton (config, database, models, tasks, migrations)
and health endpoint with passing test.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace manual community token entry with OAuth button that redirects
to VK authorization and auto-saves token via /vk/callback
- Fix groups.get API call (was groups.getById) to correctly retrieve
admin group id and name from user token response
- Fix price comparison: VK price.amount is in roubles, not kopecks
- Keep manual token input as fallback when VK_CLIENT_ID is not set
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add sync_engine.py: background asyncio loop syncing Evotor products to VK market
- Wire sync_loop into lifespan alongside health_check_loop
- Add SYNC_INTERVAL_SECONDS and VK_DEFAULT_PHOTO_PATH settings to config
- Mount default product image in docker-compose
- Add synced_at column to CachedProduct model + migration
- Show synced_at status in catalog products template
- Fix VK groups API response parsing (handle list vs dict)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Set overflow: visible on table-responsive and use data-bs-strategy="fixed"
so the filter dropdown renders outside the scroll container.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
VK connection now uses manual community token entry, so OAuth credentials
are no longer needed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Resolves#4 — VK OAuth flow caused "Security Error" because market sync
requires a community access token, not a personal user token. Replaced
OAuth with manual token input (same pattern as Evotor). Added
step-by-step instructions. Updated health checker to validate community
tokens via groups.getById instead of users.get.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Resolves#3 — widget is loaded on every page via base.html when
JIVOSITE_WIDGET_ID env var is set. Centralized Jinja2Templates instance
in web/templates_env.py with jivosite_widget_id as a global.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Resolves#2 — removes semi-automatic OAuth flow (Переподключить button,
/evotor/connect and /evotor/link routes) and makes manual token entry
the sole connect option. Adds step-by-step instructions with a direct
link to the app on Evotor marketplace (opens in new tab).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Resolves#1 — the health checker now refreshes catalog cache for all
online Evotor connections when cache is missing or older than
CATALOG_REFRESH_INTERVAL_SECONDS (default: 3600s).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Return empty list for groups/products when Evotor returns 402,
instead of crashing the refresh with an unhandled HTTP error.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace OAuth 2.0 authorization code flow with Evotor's proprietary
webhook token delivery: POST /evotor/callback receives token server-to-server,
GET /evotor/link links it to the logged-in user's account.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Update all page titles and branding in FastAPI app and templates to use Russian transliteration of product name.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Add nginx config for SSL termination and HTTP->HTTPS redirect
- Add init-letsencrypt.sh script for automated certificate provisioning
- Update docker-compose.yml: add nginx service, expose web on internal port only
- Fix Evotor OAuth token exchange: move client credentials to form body
- Add request logging for token exchange errors
- Update BASE_URL to https://evosync.ru and set default in docker-compose
- Add refresh_token field to EvotorConnection model
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Connections dashboard with add/remove flow and background health checks
- VK OAuth connection with profile info and health monitoring
- Sync configuration page with master toggle and filter summary
- Catalog browser with store/group/product tables, filter management, CSV export
- Alembic migrations for all new tables
- run/read_config.py for shell sync script DB integration
- CHANGELOG.md updated for v1.8.0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add /connections page showing all integrations with online/offline status
- Add background health checker that polls Evotor API every 10 minutes
- Add is_online and last_checked_at fields to evotor_connections table
- Replace Evotor navbar link with unified Connections link
- Redirect connect/disconnect flows to /connections
- Add Alembic migration for new columns
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>