EvoSync
Web service for syncing a product catalog from Evotor POS → VK Market. Users connect their Evotor account and a VK community; products from the cash register then appear automatically in the VK store.
Architecture
Services
| Service |
Image / Dockerfile |
Purpose |
External port |
web |
Dockerfile.web |
FastAPI app, runs Alembic migrations on start |
8080 → 8000 |
worker |
Dockerfile.web |
Celery worker (sync, health, notifications…) |
— |
beat |
Dockerfile.web |
Celery Beat — periodic task scheduler |
— |
flower |
Dockerfile.web |
Celery queue monitoring UI |
5555 |
db |
mariadb:11.4 |
Primary relational database |
— |
redis |
redis:7-alpine |
Celery broker and result backend |
— |
Stack
- Python 3.12, FastAPI 0.115, Uvicorn
- SQLAlchemy 2 + Alembic, MariaDB (PyMySQL)
- Celery 5 + Redis — background tasks, periodic catalog sync
- Jinja2 — server-side HTML rendering (
web/templates/)
- Pydantic Settings — configuration from env vars /
.env
- bcrypt — password hashing
- python-json-logger — structured JSON logs to stdout
Database Schema
| Table |
Purpose |
users |
User accounts (roles: system / admin / user; statuses: pending / active / suspended) |
evotor_connections |
User ↔ Evotor link (access_token, api_token returned to Evotor webhooks) |
vk_connections |
User ↔ VK link (user access token + VK community ID) |
sync_configs |
Per-user sync settings |
sync_filters |
Store / group inclusion filters (entity_type: store / group) |
cached_stores |
Cached list of Evotor stores |
cached_groups |
Cached Evotor product groups |
cached_products |
Cached Evotor product catalog |
vk_cached_albums |
Cached VK Market albums (product groups) |
vk_cached_products |
Cached VK Market products |
roles |
RBAC roles |
permissions |
RBAC permissions |
role_permissions |
M2M: role ↔ permission |
user_roles |
M2M: user ↔ role |
Background Tasks
Periodic tasks run via Celery Beat and are executed by the worker service.
| Task |
Schedule |
Description |
web.tasks.catalog.refresh_catalog |
Every CATALOG_REFRESH_INTERVAL_SECONDS |
Fetches stores, product groups, and products from the Evotor API for every connected user; upserts into cached_stores, cached_groups, cached_products |
web.tasks.vk_catalog.refresh_vk_catalog |
Every CATALOG_REFRESH_INTERVAL_SECONDS |
Fetches Market albums and products from VK API for every connected user; upserts into vk_cached_albums, vk_cached_products |
Evotor sync sequence per user:
GET /stores → upsert cached_stores
- For each store:
GET /stores/{id}/product-groups → upsert cached_groups
- For each store:
GET /stores/{id}/products → upsert cached_products
VK sync sequence per user:
market.getAlbums → upsert vk_cached_albums
market.get (extended=1, paginated) → upsert vk_cached_products with album membership
Per-user failures are logged and skipped — one broken token does not block other users.
Evotor stores that return 402 Payment Required (subscription limit) are silently skipped at debug log level.
Routes
Connections
| Method |
Path |
Description |
| GET |
/connections |
View Evotor and VK connection status |
| POST |
/connections/evotor |
Save / update Evotor API token manually |
| POST |
/connections/evotor/disconnect |
Remove Evotor connection |
| POST |
/connections/evotor/test |
Test Evotor connection (JSON) |
| POST |
/connections/vk |
Save / update VK token and group ID |
| POST |
/connections/vk/disconnect |
Remove VK connection |
| POST |
/connections/vk/test |
Test VK connection (JSON) |
Public / Authentication
| Method |
Path |
Description |
| GET |
/ |
Redirects to /profile or /login |
| GET |
/health |
Health check (JSON) |
| GET/POST |
/register |
User registration |
| GET |
/confirm-email |
Email confirmation via token |
| GET |
/resend-confirm |
Resend confirmation email |
| GET/POST |
/login |
Login |
| GET |
/logout |
Logout |
| GET/POST |
/forgot-password |
Request password reset |
| GET/POST |
/reset-password |
Reset password via token |
| GET/POST |
/invite |
Complete registration via invite link |
Profile (requires session)
| Method |
Path |
Description |
| GET |
/profile |
View profile |
| GET/POST |
/profile/edit |
Edit profile |
| GET/POST |
/profile/change-password |
Change password |
| GET/POST |
/profile/delete |
Delete account |
Admin panel (/admin, roles: admin / system)
| Method |
Path |
Description |
| GET |
/admin/users |
User list |
| GET |
/admin/users/{id} |
User detail |
| POST |
/admin/users/{id}/activate |
Activate user |
| POST |
/admin/users/{id}/suspend |
Suspend user |
| POST |
/admin/users/{id}/reset-password |
Reset user password |
| POST |
/admin/users/{id}/send-invite |
Send invite email |
| POST |
/admin/users/{id}/edit |
Edit user data |
| POST |
/admin/users/{id}/delete |
Delete user |
| GET |
/admin/roles |
Roles and permissions |
| POST |
/admin/roles/{id}/permissions |
Update role permissions |
Evotor Webhooks (Bearer EVOTOR_WEBHOOK_SECRET)
| Method |
Path |
Description |
| POST |
/user/create |
Evotor creates/links a user; returns api_token |
| POST |
/user/verify |
Evotor verifies user credentials; returns api_token |
| POST |
/user/token |
Evotor delivers its own access_token for a user |
Evotor Catalog (requires session)
| Method |
Path |
Description |
| GET |
/catalog |
Redirects to /catalog/stores |
| GET |
/catalog/stores |
Evotor stores with per-store sync toggle |
| GET |
/catalog/stores/{id}/groups |
Product groups with per-group sync toggle |
| GET |
/catalog/stores/{id}/products |
Products (filterable by group) |
| POST |
/catalog/stores/{id}/toggle |
Enable / disable store sync |
| POST |
/catalog/stores/{id}/groups/{gid}/toggle |
Enable / disable group sync |
VK Catalog (requires session)
| Method |
Path |
Description |
| GET |
/vk-catalog/albums |
VK Market albums (product groups) |
| GET |
/vk-catalog/albums/{id}/products |
Products in a VK album |
API Docs
| Path |
Description |
/docs |
Swagger UI |
/redoc |
ReDoc |
Configuration
All settings are read from environment variables or a .env file:
| Variable |
Default |
Description |
DATABASE_URL |
mysql+pymysql://…@db:3306/evosync |
MariaDB connection string |
REDIS_URL |
redis://redis:6379/0 |
Redis connection string |
SECRET_KEY |
change-me-in-production |
Session signing key |
BASE_URL |
http://localhost:8000 |
Public URL of the service |
EVOTOR_APP_ID |
— |
Evotor application ID |
EVOTOR_WEBHOOK_SECRET |
— |
Bearer secret for webhook endpoints |
JIVOSITE_WIDGET_ID |
— |
JivoSite widget ID |
VK_DEFAULT_PHOTO_PATH |
/app/default_product.png |
Fallback image path for VK products |
VK_API_VERSION |
5.199 |
VK API version |
CATALOG_REFRESH_INTERVAL_SECONDS |
3600 |
Evotor + VK catalog sync interval (s) |
INVITE_EXPIRE_HOURS |
48 |
Invite link TTL in hours |
EMAIL_PROVIDER |
console |
Email provider (console / smtp / …) |
SMS_PROVIDER |
console |
SMS provider |
FLOWER_USER / FLOWER_PASSWORD |
admin / changeme |
Basic Auth credentials for Flower |
Running
App is available at http://localhost:8080.
Flower (queue monitor) at http://localhost:5555.
Development
Tests