Disable bootstrap by default and document ENABLE_BOOTSTRAP
This commit is contained in:
106
CONTEXT.md
Normal file
106
CONTEXT.md
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
# Zkart Context
|
||||||
|
|
||||||
|
## Что это
|
||||||
|
Одностраничное Flask-приложение с матрицей:
|
||||||
|
- `вендор -> продукты -> категории`
|
||||||
|
- в двух режимах: `Инфраструктура` и `ИБ`.
|
||||||
|
|
||||||
|
## Основные файлы
|
||||||
|
- `main.py` - Flask-приложение (главная страница, API, админка, инициализация/миграция БД, импорт ИБ при необходимости).
|
||||||
|
- `requirements.txt` - зависимости Python.
|
||||||
|
- `matrix.db` - SQLite-база со всеми сущностями по двум режимам.
|
||||||
|
- `Dockerfile` - контейнеризация приложения.
|
||||||
|
- `docker-compose.yml` - запуск сервиса в Docker.
|
||||||
|
- `.dockerignore` - исключения для docker build context.
|
||||||
|
- `mont_logo.png` - логотип, используется на главной.
|
||||||
|
|
||||||
|
## Роуты
|
||||||
|
- `/` - основной интерфейс с фильтрами.
|
||||||
|
- `/api/data?scope=infra|ib` - JSON с данными выбранного режима.
|
||||||
|
- `/health` - проверка статуса.
|
||||||
|
- `/sdjlkfhsjkadahjksdhjgfkhsssssdjkjfljsdfjklsdajfkldsjflksdjfkldsj` - админка.
|
||||||
|
- `/assets/mont-logo` - отдача логотипа.
|
||||||
|
|
||||||
|
## API `/api/data`
|
||||||
|
Возвращает:
|
||||||
|
- `vendors`
|
||||||
|
- `categories`
|
||||||
|
- `products`
|
||||||
|
- `product_links` (`product_id -> category_id`)
|
||||||
|
- `links` (агрегированные `vendor_id -> category_id`, для совместимости)
|
||||||
|
|
||||||
|
`scope`:
|
||||||
|
- `infra` - инфраструктурный контур.
|
||||||
|
- `ib` (или `sec/security`) - контур ИБ.
|
||||||
|
|
||||||
|
## Админ-доступ
|
||||||
|
- Логин: `batman`
|
||||||
|
- Пароль: `batmannotmont`
|
||||||
|
|
||||||
|
## Админка: что умеет
|
||||||
|
- Переключение режима `Инфраструктура / ИБ` через `?scope=...`.
|
||||||
|
- Добавление/удаление вендоров.
|
||||||
|
- Добавление/удаление категорий.
|
||||||
|
- Добавление/удаление продуктов (продукт принадлежит вендору).
|
||||||
|
- Редактирование матрицы `продукт × категория` чекбоксами.
|
||||||
|
- При сохранении автоматически пересобираются агрегированные связи `вендор × категория`.
|
||||||
|
|
||||||
|
## Структура БД (SQLite)
|
||||||
|
### Infra
|
||||||
|
- `vendors`
|
||||||
|
- `categories`
|
||||||
|
- `vendor_categories`
|
||||||
|
- `products`
|
||||||
|
- `product_categories`
|
||||||
|
|
||||||
|
### IB
|
||||||
|
- `ib_vendors`
|
||||||
|
- `ib_categories`
|
||||||
|
- `ib_vendor_categories`
|
||||||
|
- `ib_products`
|
||||||
|
- `ib_product_categories`
|
||||||
|
|
||||||
|
## Инициализация данных
|
||||||
|
- Включается только при `ENABLE_BOOTSTRAP=1`.
|
||||||
|
- Infra: исторические данные приложения.
|
||||||
|
- IB:
|
||||||
|
- при первом запуске может заполняться из `Z-card_РФ.xlsx` (вкладка `инфобез`), если файл доступен;
|
||||||
|
- иначе используется встроенный fallback-набор.
|
||||||
|
- Для пустых `products` может выполняться bootstrap: для каждого вендора создается `Базовый продукт` и получает текущие связи категорий.
|
||||||
|
- При `ENABLE_BOOTSTRAP=0` (по умолчанию) автосидинг/автоимпорт не выполняются, приложение работает с текущими данными `matrix.db`.
|
||||||
|
|
||||||
|
## Запуск
|
||||||
|
```bash
|
||||||
|
python3 -m venv .venv
|
||||||
|
.venv/bin/python -m ensurepip --upgrade
|
||||||
|
.venv/bin/python -m pip install -r requirements.txt
|
||||||
|
.venv/bin/python main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Запуск через Docker
|
||||||
|
```bash
|
||||||
|
docker compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
Порт:
|
||||||
|
- `5000:5000`
|
||||||
|
|
||||||
|
Переменные окружения:
|
||||||
|
- `SECRET_KEY` (если не задан, используется дефолт `change-me-please`).
|
||||||
|
- `ENABLE_BOOTSTRAP` (по умолчанию `0`):
|
||||||
|
- `0`: не выполнять автозаполнение;
|
||||||
|
- `1`: разрешить seed/bootstrap/import на старте.
|
||||||
|
|
||||||
|
## Git
|
||||||
|
- Remote: `https://git.ruslan.xyz/ruslan/mont_vendor_maps.git`
|
||||||
|
- Логин для push: `ruslan@ipcom.su`
|
||||||
|
- Пароль/токен не хранить в репозитории и контекстных файлах; использовать через credential manager или переменные окружения.
|
||||||
|
|
||||||
|
## Заметки
|
||||||
|
- Приложение хранит данные в `matrix.db`.
|
||||||
|
- Для продакшена рекомендуется задать переменную `SECRET_KEY`.
|
||||||
|
- В режиме `ИБ` интерфейс получает более красный фон (отдельная визуальная тема).
|
||||||
|
- На главной:
|
||||||
|
- логотип MONT слева без овального контейнера;
|
||||||
|
- hero-блок с горным фоном;
|
||||||
|
- подпись внизу справа: `Made by Galyaviev`, `ruslan@ipcom.su`.
|
||||||
@@ -42,8 +42,13 @@ docker compose up -d --build
|
|||||||
|
|
||||||
## Переменные окружения
|
## Переменные окружения
|
||||||
- `SECRET_KEY` — секрет Flask-сессии.
|
- `SECRET_KEY` — секрет Flask-сессии.
|
||||||
|
- `ENABLE_BOOTSTRAP` — управление стартовым наполнением данных:
|
||||||
|
- `0` (по умолчанию): не выполнять автосидинг/автоимпорт;
|
||||||
|
- `1`: разрешить bootstrap (seed + импорт из `infra1..infra4` при подходящих условиях).
|
||||||
|
|
||||||
## База данных
|
## База данных
|
||||||
SQLite: `matrix.db`.
|
SQLite: `matrix.db`.
|
||||||
|
|
||||||
Содержит данные по двум контурам (`infra` и `ib`), включая продукты и связи категорий.
|
Содержит данные по двум контурам (`infra` и `ib`), включая продукты и связи категорий.
|
||||||
|
|
||||||
|
Если `matrix.db` уже заполнена, запускайте с `ENABLE_BOOTSTRAP=0` (дефолт), чтобы не выполнять лишнюю инициализацию.
|
||||||
|
|||||||
13
main.py
13
main.py
@@ -24,6 +24,7 @@ ADMIN_PASSWORD = "batmannotmont"
|
|||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.secret_key = os.getenv("SECRET_KEY", "change-me-please")
|
app.secret_key = os.getenv("SECRET_KEY", "change-me-please")
|
||||||
|
ENABLE_BOOTSTRAP = os.getenv("ENABLE_BOOTSTRAP", "0").strip().lower() in {"1", "true", "yes", "on"}
|
||||||
|
|
||||||
|
|
||||||
def get_db() -> sqlite3.Connection:
|
def get_db() -> sqlite3.Connection:
|
||||||
@@ -299,11 +300,11 @@ def init_db() -> None:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
has_data = conn.execute("SELECT EXISTS(SELECT 1 FROM vendors)").fetchone()[0]
|
has_data = conn.execute("SELECT EXISTS(SELECT 1 FROM vendors)").fetchone()[0]
|
||||||
if not has_data:
|
if not has_data and ENABLE_BOOTSTRAP:
|
||||||
seed_data(conn)
|
seed_data(conn)
|
||||||
|
|
||||||
has_ib_data = conn.execute("SELECT EXISTS(SELECT 1 FROM ib_vendors)").fetchone()[0]
|
has_ib_data = conn.execute("SELECT EXISTS(SELECT 1 FROM ib_vendors)").fetchone()[0]
|
||||||
if not has_ib_data:
|
if not has_ib_data and ENABLE_BOOTSTRAP:
|
||||||
ib_matrix = None
|
ib_matrix = None
|
||||||
from_xlsx = load_matrices_from_xlsx()
|
from_xlsx = load_matrices_from_xlsx()
|
||||||
if from_xlsx:
|
if from_xlsx:
|
||||||
@@ -311,9 +312,11 @@ def init_db() -> None:
|
|||||||
if not ib_matrix:
|
if not ib_matrix:
|
||||||
ib_matrix = IB_MATRIX
|
ib_matrix = IB_MATRIX
|
||||||
seed_ib_data(conn, ib_matrix)
|
seed_ib_data(conn, ib_matrix)
|
||||||
bootstrap_products_from_vendor_links(conn, "infra")
|
|
||||||
bootstrap_products_from_vendor_links(conn, "ib")
|
if ENABLE_BOOTSTRAP:
|
||||||
import_infra_products_from_json(conn)
|
bootstrap_products_from_vendor_links(conn, "infra")
|
||||||
|
bootstrap_products_from_vendor_links(conn, "ib")
|
||||||
|
import_infra_products_from_json(conn)
|
||||||
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|||||||
Reference in New Issue
Block a user